mini_internal/
attr.rs

1use proc_macro2::Ident;
2use syn::{Attribute, Field, LitStr, Result, Variant};
3
4/// Find the value of a #[serde(rename = "...")] attribute.
5fn attr_rename(attrs: &[Attribute]) -> Result<Option<String>> {
6    let mut rename = None;
7
8    for attr in attrs {
9        if !attr.path().is_ident("serde") {
10            continue;
11        }
12
13        attr.parse_nested_meta(|meta| {
14            if meta.path.is_ident("rename") {
15                let s: LitStr = meta.value()?.parse()?;
16                if rename.is_some() {
17                    return Err(meta.error("duplicate rename attribute"));
18                }
19                rename = Some(s.value());
20                Ok(())
21            } else {
22                Err(meta.error("unsupported attribute"))
23            }
24        })?;
25    }
26
27    Ok(rename)
28}
29
30/// Determine the name of a field, respecting a rename attribute.
31pub fn name_of_field(field: &Field) -> Result<String> {
32    let rename = attr_rename(&field.attrs)?;
33    Ok(rename.unwrap_or_else(|| unraw(field.ident.as_ref().unwrap())))
34}
35
36/// Determine the name of a variant, respecting a rename attribute.
37pub fn name_of_variant(var: &Variant) -> Result<String> {
38    let rename = attr_rename(&var.attrs)?;
39    Ok(rename.unwrap_or_else(|| unraw(&var.ident)))
40}
41
42fn unraw(ident: &Ident) -> String {
43    ident.to_string().trim_start_matches("r#").to_owned()
44}