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!(
35                    "warning: unknown rename_all value \"{}\" — {e}; attribute ignored",
36                    value.value(),
37                );
38                None
39            }
40        }
41    })
42}
43
44/// Parses `#[serde(rename = "...")]` from attributes.
45pub fn parse_rename(attrs: &[syn::Attribute]) -> Option<String> {
46    find_serde_meta(attrs, |meta| {
47        if !meta.path.is_ident("rename") {
48            return None;
49        }
50        let value = meta.value().ok()?.parse::<syn::LitStr>().ok()?;
51        Some(value.value())
52    })
53}
54
55/// Checks for `#[serde(skip)]` or `#[serde(skip_serializing)]` on a field.
56pub fn is_skipped(attrs: &[syn::Attribute]) -> bool {
57    find_serde_meta(attrs, |meta| {
58        if meta.path.is_ident("skip") || meta.path.is_ident("skip_serializing") {
59            Some(true)
60        } else {
61            None
62        }
63    })
64    .unwrap_or(false)
65}
66
67/// Checks for `#[serde(default)]` on a field.
68pub fn has_default(attrs: &[syn::Attribute]) -> bool {
69    find_serde_meta(attrs, |meta| {
70        if meta.path.is_ident("default") {
71            Some(true)
72        } else {
73            None
74        }
75    })
76    .unwrap_or(false)
77}