@@ -9,27 +9,47 @@ use syn::{
99pub use try_from:: TryTransitionFrom ;
1010pub use try_into:: TryTransitionInto ;
1111
12+ use crate :: transitive:: TOO_FEW_TYPES_ERR_MSG ;
13+
1214/// A path list that may contain a custom error type.
1315pub struct FalliblePathList {
14- type_list : Vec < Type > ,
16+ /// First type in the transitive conversion. ie. `A` in
17+ /// `#[transitive(try_from(A, B, C, D, E))]`
18+ first_type : Type ,
19+ /// Intermediate types for the transitive conversion. ie. `[B, .., D]` in
20+ /// `#[transitive(try_from(A, B, C, D, E))]`
21+ intermediate_types : Vec < Type > ,
22+ /// Last type in the transitive conversion. ie. `E` in
23+ /// `#[transitive(try_from(A, B, C, D, E))]`
24+ last_type : Type ,
1525 error : Option < Type > ,
1626}
1727
1828impl Parse for FalliblePathList {
1929 fn parse ( input : ParseStream ) -> SynResult < Self > {
30+ let error_span = input. span ( ) ;
2031 let attr_list = Punctuated :: < Item , Token ! [ , ] > :: parse_terminated ( input) ?;
2132
22- let mut type_list = Vec :: with_capacity ( attr_list. len ( ) ) ;
33+ let mut attr_list_iter = attr_list. into_iter ( ) ;
34+ let ( first_type, mut last_type) = match ( attr_list_iter. next ( ) , attr_list_iter. next ( ) ) {
35+ ( Some ( Item :: Type ( ft) ) , Some ( Item :: Type ( lt) ) ) => ( ft, lt) ,
36+ _ => return Err ( SynError :: new ( error_span, TOO_FEW_TYPES_ERR_MSG ) ) ,
37+ } ;
38+
39+ let mut intermediate_types = Vec :: with_capacity ( attr_list_iter. len ( ) ) ;
2340 let mut error = None ;
2441
25- for attr in attr_list {
42+ for attr in attr_list_iter {
2643 match attr {
2744 Item :: Type ( ty) if error. is_some ( ) => {
2845 let msg = "types not allowed after 'error'" ;
2946 return Err ( SynError :: new_spanned ( ty, msg) ) ;
3047 }
3148 // Just a regular type path in the conversion path
32- Item :: Type ( ty) => type_list. push ( ty) ,
49+ Item :: Type ( ty) => {
50+ intermediate_types. push ( last_type) ;
51+ last_type = ty;
52+ }
3353 Item :: Error ( err) if error. is_some ( ) => {
3454 let msg = "'error' not allowed multiple times" ;
3555 return Err ( SynError :: new_spanned ( err, msg) ) ;
@@ -39,7 +59,12 @@ impl Parse for FalliblePathList {
3959 }
4060 }
4161
42- let output = Self { type_list, error } ;
62+ let output = Self {
63+ first_type,
64+ intermediate_types,
65+ last_type,
66+ error,
67+ } ;
4368
4469 Ok ( output)
4570 }
0 commit comments