From c828e834e71bd1f66d43b393ddae5d5e5002ccce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 1 Aug 2023 12:18:49 +0200 Subject: [PATCH] Use proper spanned errors --- src/parse.rs | 93 +++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index b009cae..5e341e3 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -82,7 +82,7 @@ impl Parse for Input { } }; - let fields = fields_from_ast(&syn_fields.named); + let fields = fields_from_ast(&syn_fields.named)?; let lifetimes = lifetimes(&derive_input.generics); @@ -97,58 +97,55 @@ impl Parse for Input { } } -fn fields_from_ast(fields: &syn::punctuated::Punctuated) -> Vec { +fn fields_from_ast( + fields: &syn::punctuated::Punctuated, +) -> Result> { // serde::internals::ast.rs:L183 fields .iter() .enumerate() - .map(|(i, field)| Field { - // these are https://docs.rs/syn/1.0.13/syn/struct.Field.html - label: match &field.ident { - Some(ident) => ident.to_string(), - None => { - // TODO: does this happen? - panic!("input struct must have named fields"); - } - }, - member: match &field.ident { - Some(ident) => syn::Member::Named(ident.clone()), - None => { - // TODO: does this happen? - panic!("input struct must have named fields"); - } - }, - index: i, - // TODO: make this... more concise? handle errors? the thing with the spans? - skip_serializing_if: { - let mut skip_serializing_if = None; - for attr in &field.attrs { - if attr.path().is_ident("serde") { - attr.parse_nested_meta(|meta| { - if meta.path.is_ident("skip_serializing_if") { - let litstr: LitStr = meta - .value() - .expect(r#"skip_serializing_if = "literal""#) - .parse() - .expect(r#"skip_serializing_if = "literal""#); - let tokens = syn::parse_str(&litstr.value()) - .expect("Failed to parse attribute"); - if skip_serializing_if.is_some() { - panic!("Multiple attributes for skip_serializing_if"); - } - skip_serializing_if = Some(syn::parse2(tokens).unwrap()); - Ok(()) - } else { - panic!("Unkown field attribute") - } - }) - .expect("Failed to parse attribute"); + .map(|(i, field)| { + Ok(Field { + // these are https://docs.rs/syn/2.0.28/syn/struct.Field.html + label: match &field.ident { + Some(ident) => ident.to_string(), + None => { + return Err(Error::new_spanned(fields, "Tuple struct are not supported")); } - } - skip_serializing_if - }, - ty: field.ty.clone(), - original: field.clone(), + }, + member: match &field.ident { + Some(ident) => syn::Member::Named(ident.clone()), + None => { + return Err(Error::new_spanned(fields, "Tuple struct are not supported")); + } + }, + index: i, + // TODO: make this... more concise? handle errors? the thing with the spans? + skip_serializing_if: { + let mut skip_serializing_if = None; + for attr in &field.attrs { + if attr.path().is_ident("serde") { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("skip_serializing_if") { + let litstr: LitStr = meta.value()?.parse()?; + let tokens = syn::parse_str(&litstr.value())?; + if skip_serializing_if.is_some() { + return Err(meta + .error("Multiple attributes for skip_serializing_if")); + } + skip_serializing_if = Some(syn::parse2(tokens)?); + Ok(()) + } else { + Err(meta.error("Unkown field attribute")) + } + })?; + } + } + skip_serializing_if + }, + ty: field.ty.clone(), + original: field.clone(), + }) }) .collect() }