serde_attributes/rename/
syn.rs1use syn::{Error as SynError, Expr, ExprLit, Lit, LitStr, Meta, MetaList};
2
3use crate::symbol::{DESERIALIZE, SERIALIZE, Symbol};
4
5use super::{Rename, RenameIndependent};
6
7pub const RENAME: Symbol = Symbol("rename");
9
10impl Rename {
11 pub fn try_from_meta<'a>(meta: &'a Meta, attr_name: Symbol) -> Result<Self, FromMetaError<'a>> {
13 match meta {
14 Meta::NameValue(meta_name_value) if meta_name_value.path == attr_name => {
15 match &meta_name_value.value {
16 Expr::Lit(ExprLit {
17 lit: Lit::Str(lit), ..
18 }) => Ok(Self::Normal(lit.value())),
19 expr => Err(FromMetaError::MetaNameValueExprTypeMismatch(expr)),
20 }
21 }
22 Meta::List(meta_list) if meta_list.path == attr_name => {
23 let mut ser_name = None;
24 let mut de_name = None;
25
26 meta_list.parse_nested_meta(|parse_nested_meta| {
27 if parse_nested_meta.path == SERIALIZE {
28 let value = parse_nested_meta.value()?;
29 let lit: LitStr = value.parse()?;
30 ser_name = Some(lit.value());
31 } else if parse_nested_meta.path == DESERIALIZE {
32 let value = parse_nested_meta.value()?;
33 let lit: LitStr = value.parse()?;
34 de_name = Some(lit.value());
35 } else {
36 return Err(parse_nested_meta.error(format_args!(
37 "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
38 attr_name,
39 )));
40 }
41 Ok(())
42 }).map_err(|err| FromMetaError::MetaListTypeMismatch(meta_list, err))?;
43
44 match (ser_name, de_name) {
45 (None, None) => Err(FromMetaError::AtLeastOneOfSerAndDe),
46 (None, Some(de_name)) => {
47 Ok(Self::Independent(RenameIndependent::Deserialize(de_name)))
48 }
49 (Some(ser_name), None) => {
50 Ok(Self::Independent(RenameIndependent::Serialize(ser_name)))
51 }
52 (Some(ser_name), Some(de_name)) => {
53 Ok(Self::Independent(RenameIndependent::Both {
54 serialize: ser_name,
55 deserialize: de_name,
56 }))
57 }
58 }
59 }
60 meta => Err(FromMetaError::MetaTypeOrPathMismatch(meta)),
61 }
62 }
63}
64
65impl<'a> core::convert::TryFrom<&'a Meta> for Rename {
67 type Error = FromMetaError<'a>;
68
69 fn try_from(meta: &'a Meta) -> Result<Self, Self::Error> {
70 Self::try_from_meta(meta, RENAME)
71 }
72}
73
74pub enum FromMetaError<'a> {
75 MetaTypeOrPathMismatch(&'a Meta),
76 MetaNameValueExprTypeMismatch(&'a Expr),
77 MetaListTypeMismatch(&'a MetaList, SynError),
78 AtLeastOneOfSerAndDe,
79}
80impl<'a> core::fmt::Debug for FromMetaError<'a> {
81 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82 match self {
83 Self::MetaTypeOrPathMismatch(_) => write!(f, "MetaTypeOrPathMismatch"),
84 Self::MetaNameValueExprTypeMismatch(_) => write!(f, "MetaNameValueExprTypeMismatch"),
85 Self::MetaListTypeMismatch(_, _) => write!(f, "MetaListTypeMismatch"),
86 Self::AtLeastOneOfSerAndDe => write!(f, "AtLeastOneOfSerAndDe"),
87 }
88 }
89}
90impl<'a> core::fmt::Display for FromMetaError<'a> {
91 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
92 write!(f, "{self:?}")
93 }
94}
95
96impl<'a> core::error::Error for FromMetaError<'a> {}