serde_attributes/rename/
syn.rs

1use syn::{Error as SynError, Expr, ExprLit, Lit, LitStr, Meta, MetaList};
2
3use crate::symbol::{DESERIALIZE, SERIALIZE, Symbol};
4
5use super::{Rename, RenameIndependent};
6
7/// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/symbol.rs#L23)
8pub const RENAME: Symbol = Symbol("rename");
9
10impl Rename {
11    /// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/attr.rs#L319-L333)
12    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
65/// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/attr.rs#L319-L333)
66impl<'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> {}