Skip to main content

vercel_rpc_cli/parser/
serde.rs

1use crate::model::RenameRule;
2
3/// Walks `#[serde(...)]` attributes and calls `visitor` for each nested meta item.
4/// Returns the last value produced by the visitor, or `None` if no match.
5fn find_serde_meta<T>(
6    attrs: &[syn::Attribute],
7    mut visitor: impl FnMut(&syn::meta::ParseNestedMeta) -> Option<T>,
8) -> Option<T> {
9    let mut result = None;
10    for attr in attrs {
11        if !attr.path().is_ident("serde") {
12            continue;
13        }
14        let _ = attr.parse_nested_meta(|meta| {
15            if let Some(value) = visitor(&meta) {
16                result = Some(value);
17            }
18            Ok(())
19        });
20    }
21    result
22}
23
24/// Parses `#[serde(rename_all = "...")]` from attributes.
25pub fn parse_rename_all(attrs: &[syn::Attribute]) -> Option<RenameRule> {
26    find_serde_meta(attrs, |meta| {
27        if !meta.path.is_ident("rename_all") {
28            return None;
29        }
30        let value = meta.value().ok()?.parse::<syn::LitStr>().ok()?;
31        match value.value().parse::<RenameRule>() {
32            Ok(rule) => Some(rule),
33            Err(e) => {
34                eprintln!("warning: {e} (ignored)");
35                None
36            }
37        }
38    })
39}
40
41/// Parses `#[serde(rename = "...")]` from attributes.
42pub fn parse_rename(attrs: &[syn::Attribute]) -> Option<String> {
43    find_serde_meta(attrs, |meta| {
44        if !meta.path.is_ident("rename") {
45            return None;
46        }
47        let value = meta.value().ok()?.parse::<syn::LitStr>().ok()?;
48        Some(value.value())
49    })
50}
51
52/// Checks for `#[serde(skip)]` or `#[serde(skip_serializing)]` on a field.
53pub fn is_skipped(attrs: &[syn::Attribute]) -> bool {
54    find_serde_meta(attrs, |meta| {
55        if meta.path.is_ident("skip") || meta.path.is_ident("skip_serializing") {
56            Some(true)
57        } else {
58            None
59        }
60    })
61    .unwrap_or(false)
62}
63
64/// Checks for `#[serde(default)]` on a field.
65pub fn has_default(attrs: &[syn::Attribute]) -> bool {
66    find_serde_meta(attrs, |meta| {
67        if meta.path.is_ident("default") {
68            Some(true)
69        } else {
70            None
71        }
72    })
73    .unwrap_or(false)
74}