@@ -194,7 +194,7 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
194194 . map ( |ContainerAnnotation ( target_enum) | ( target_enum, VariantsMapping ( HashMap :: new ( ) ) ) )
195195 . collect :: < HashMap < _ , _ > > ( ) ;
196196
197- for ( source_variant, variant_annotations) in variants_annotations {
197+ for ( source_variant, mut variant_annotations) in variants_annotations {
198198 let mut target_variants = variant_annotations
199199 . variant_annotations
200200 . into_iter ( )
@@ -217,8 +217,8 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
217217 . map ( |( target_variant, _span) | target_variant)
218218 . unwrap_or_else ( || VariantIdent ( source_variant. ident . clone ( ) ) ) ;
219219
220- let fields_mapping = get_fields_mapping (
221- & variant_annotations. fields_annotations ,
220+ let fields_annotations = extract_fields_annotations (
221+ & mut variant_annotations. fields_annotations ,
222222 target_enum,
223223 & target_variant,
224224 ) ?;
@@ -228,7 +228,7 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
228228 Fields :: Unit => VariantMapping :: Unit { source_variant } ,
229229 Fields :: Unnamed ( _) => VariantMapping :: Tuple {
230230 source_variant,
231- fields_mapping : fields_mapping
231+ fields_mapping : fields_annotations
232232 . into_iter ( )
233233 . map ( |source_to_target| match source_to_target {
234234 (
@@ -247,7 +247,7 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
247247 } ,
248248 Fields :: Named ( _) => VariantMapping :: Struct {
249249 source_variant,
250- fields_mapping : fields_mapping
250+ fields_mapping : fields_annotations
251251 . into_iter ( )
252252 . map ( |source_to_target| match source_to_target {
253253 (
@@ -273,16 +273,11 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
273273
274274 variants_mapping. insert ( target_variant, variant_mappings) ;
275275 }
276- source_variants. insert ( VariantIdent ( source_variant. ident . clone ( ) ) , source_variant) ;
277276
278- for ( target_enum, ( _, span) ) in target_variants {
279- Err ( syn:: Error :: new (
280- span,
281- format ! (
282- "target enum `{target_enum}` is not specified in this enum's #[enum_into] annotation"
283- ) ,
284- ) ) ?
285- }
277+ check_unused_variants_annotations ( target_variants) ?;
278+ check_unused_fields_annotations ( & target_enums, variant_annotations. fields_annotations ) ?;
279+
280+ source_variants. insert ( VariantIdent ( source_variant. ident . clone ( ) ) , source_variant) ;
286281 }
287282
288283 Ok ( EnumIntoGenerator {
@@ -293,29 +288,66 @@ impl TryFrom<ParsedEnumInto> for EnumIntoGenerator {
293288 }
294289}
295290
296- fn get_fields_mapping (
297- fields_annotations : & HashMap < FieldRef , FieldAnnotations > ,
291+ fn check_unused_variants_annotations (
292+ target_variants : HashMap < ContainerIdent , ( VariantIdent , Span ) > ,
293+ ) -> syn:: Result < ( ) > {
294+ for ( target_enum, ( _, span) ) in target_variants {
295+ Err ( syn:: Error :: new (
296+ span,
297+ format ! (
298+ "target enum `{target_enum}` is not specified in this enum's #[enum_into] annotation"
299+ ) ,
300+ ) ) ?
301+ }
302+ Ok ( ( ) )
303+ }
304+
305+ fn check_unused_fields_annotations (
306+ target_enums : & HashMap < ContainerIdent , VariantsMapping > ,
307+ fields_annotations : HashMap < FieldRef , FieldAnnotations > ,
308+ ) -> syn:: Result < ( ) > {
309+ for field_annotations in fields_annotations. into_values ( ) {
310+ for field_annotation in field_annotations. fields_annotations {
311+ if target_enums. contains_key ( & field_annotation. target_enum ) {
312+ Err ( syn:: Error :: new (
313+ field_annotation. variant_span ,
314+ "Field mapping for unexpected enum and variant combination" ,
315+ ) ) ?
316+ } else {
317+ Err ( syn:: Error :: new (
318+ field_annotation. enum_span ,
319+ "Field mapping for unknown enum" ,
320+ ) ) ?
321+ }
322+ }
323+ }
324+
325+ Ok ( ( ) )
326+ }
327+
328+ fn extract_fields_annotations (
329+ fields_annotations : & mut HashMap < FieldRef , FieldAnnotations > ,
298330 target_enum : & ContainerIdent ,
299331 target_variant : & VariantIdent ,
300332) -> syn:: Result < BTreeMap < FieldRef , FieldAnnotation > > {
301333 Ok ( fields_annotations
302- . iter ( )
334+ . iter_mut ( )
303335 . filter_map ( |( source_field, field_annotations) | {
304- let annotations = field_annotations
336+ let mut annotations = field_annotations
305337 . fields_annotations
306- . iter ( )
307- . filter ( |field_annotation| {
338+ . extract_if ( .., |field_annotation| {
308339 field_annotation. target_enum == * target_enum
309340 && field_annotation. target_variant == * target_variant
310341 } )
311342 . collect :: < Vec < _ > > ( ) ;
312- match annotations. len ( ) {
313- 0 => None ,
314- 1 => Some ( Ok ( ( source_field. clone ( ) , annotations[ 0 ] . clone ( ) ) ) ) ,
315- _ => Some ( Err ( syn:: Error :: new (
343+ let annotation = annotations. pop ( ) ;
344+ if annotations. pop ( ) . is_some ( ) {
345+ Some ( Err ( syn:: Error :: new (
316346 field_annotations. field_span ,
317347 format ! ( "Multiple mapping found for target enum `{target_enum}`" ) ,
318- ) ) ) ,
348+ ) ) )
349+ } else {
350+ annotation. map ( |annotation| Ok ( ( source_field. clone ( ) , annotation) ) )
319351 }
320352 } )
321353 . collect :: < syn:: Result < Vec < _ > > > ( ) ?
0 commit comments