sea_query_derive/iden/
attr.rs

1use std::convert::{TryFrom, TryInto};
2
3use syn::spanned::Spanned;
4use syn::{Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta};
5
6use super::{error::ErrorMsg, path::IdenPath};
7
8#[derive(PartialEq, Eq)]
9pub(crate) enum IdenAttr {
10    Rename(String),
11    Method(Ident),
12    Flatten,
13}
14
15impl IdenAttr {
16    fn extract_method(meta: Meta) -> syn::Result<Self> {
17        match meta {
18            Meta::NameValue(nv) => match nv.value {
19                Expr::Lit(ExprLit { lit, .. }) => match lit {
20                    Lit::Str(name) => {
21                        Ok(Self::Method(Ident::new(name.value().as_str(), name.span())))
22                    }
23                    _ => Err(Error::new_spanned(nv.eq_token, ErrorMsg::WrongLiteral)),
24                },
25                _ => Err(Error::new_spanned(nv, ErrorMsg::WrongLiteral)),
26            },
27            a => Err(Error::new_spanned(
28                a,
29                ErrorMsg::WrongNamedValueFormat(IdenPath::Method, IdenPath::Method),
30            )),
31        }
32    }
33
34    fn extract_iden(meta: Meta) -> syn::Result<Self> {
35        match &meta {
36            Meta::NameValue(nv) => match &nv.value {
37                Expr::Lit(ExprLit { lit, .. }) => match lit {
38                    Lit::Str(lit) => Ok(IdenAttr::Rename(lit.value())),
39                    _ => Err(Error::new_spanned(&nv.value, ErrorMsg::WrongLiteral)),
40                },
41                _ => Err(Error::new_spanned(nv, ErrorMsg::WrongLiteral)),
42            },
43            Meta::List(list) if list.path.is_ident("iden") => {
44                let mut iden_attr: Option<Self> = None;
45                list.parse_nested_meta(|nested| {
46                    if nested.path.is_ident(&IdenPath::Flatten) {
47                        iden_attr = Some(IdenAttr::Flatten);
48                        Ok(())
49                    } else if nested.path.is_ident(&IdenPath::Rename) {
50                        let value = nested.value()?;
51                        let value: LitStr = value.parse()?;
52                        iden_attr = Some(IdenAttr::Rename(value.value()));
53                        Ok(())
54                    } else if nested.path.is_ident(&IdenPath::Method) {
55                        let value = nested.value()?;
56                        let value: LitStr = value.parse()?;
57                        iden_attr = Some(IdenAttr::Method(Ident::new(&value.value(), meta.span())));
58                        Ok(())
59                    } else {
60                        Err(Error::new_spanned(
61                            &meta,
62                            ErrorMsg::UnsupportedKeyword(nested.path.get_ident().unwrap().clone()),
63                        ))
64                    }
65                })?;
66                iden_attr.ok_or(Error::new_spanned(meta, ErrorMsg::WrongListFormat))
67            }
68            a => Err(Error::new_spanned(a, ErrorMsg::WrongAttributeFormat)),
69        }
70    }
71}
72
73impl TryFrom<&Attribute> for IdenAttr {
74    type Error = Error;
75
76    fn try_from(value: &Attribute) -> Result<Self, Self::Error> {
77        value.meta.clone().try_into()
78    }
79}
80
81impl TryFrom<Meta> for IdenAttr {
82    type Error = Error;
83
84    fn try_from(value: Meta) -> Result<Self, Self::Error> {
85        let path = value.path();
86        if path.is_ident(&IdenPath::Method) {
87            Self::extract_method(value)
88        } else if path.is_ident(&IdenPath::Iden) {
89            Self::extract_iden(value)
90        } else {
91            todo!()
92        }
93    }
94}