Skip to main content

vercel_rpc_cli/parser/
types.rs

1use syn::{Fields, FieldsNamed, Type};
2
3use super::serde as serde_attr;
4use crate::model::{FieldDef, RustType};
5
6/// Converts a `syn::Type` into our `RustType` representation.
7///
8/// Handles paths (simple and generic), references, tuples, arrays, and unit.
9/// Unknown or unsupported types fall back to their token representation.
10pub fn extract_rust_type(ty: &Type) -> RustType {
11    match ty {
12        Type::Path(type_path) => {
13            let Some(segment) = type_path.path.segments.last() else {
14                let token_str = quote::quote!(#ty).to_string();
15                return RustType::simple(token_str);
16            };
17            let name = segment.ident.to_string();
18            let generics = extract_generic_args(&segment.arguments);
19
20            if generics.is_empty() {
21                RustType::simple(name)
22            } else {
23                RustType::with_generics(name, generics)
24            }
25        }
26
27        Type::Reference(type_ref) => extract_rust_type(&type_ref.elem),
28
29        Type::Tuple(tuple) => {
30            if tuple.elems.is_empty() {
31                RustType::simple("()")
32            } else {
33                let inner: Vec<RustType> = tuple.elems.iter().map(extract_rust_type).collect();
34                RustType::with_generics("tuple", inner)
35            }
36        }
37
38        Type::Array(array) => {
39            let elem = extract_rust_type(&array.elem);
40            RustType::with_generics("Array", vec![elem])
41        }
42
43        Type::Slice(slice) => {
44            let elem = extract_rust_type(&slice.elem);
45            RustType::with_generics("Array", vec![elem])
46        }
47
48        _ => {
49            let token_str = quote::quote!(#ty).to_string();
50            RustType::simple(token_str)
51        }
52    }
53}
54
55/// Extracts generic type arguments from a path segment (e.g. `<String, i32>`).
56fn extract_generic_args(arguments: &syn::PathArguments) -> Vec<RustType> {
57    match arguments {
58        syn::PathArguments::AngleBracketed(args) => args
59            .args
60            .iter()
61            .filter_map(|arg| match arg {
62                syn::GenericArgument::Type(ty) => Some(extract_rust_type(ty)),
63                _ => None,
64            })
65            .collect(),
66        _ => vec![],
67    }
68}
69
70/// Extracts named fields from a struct/variant into `FieldDef` values,
71/// including serde attributes (`rename`, `skip`, `default`).
72pub fn extract_struct_fields(fields: &Fields) -> Vec<FieldDef> {
73    match fields {
74        Fields::Named(FieldsNamed { named, .. }) => named
75            .iter()
76            .filter_map(|f| {
77                let name = f.ident.as_ref()?.to_string();
78                let ty = extract_rust_type(&f.ty);
79                let rename = serde_attr::parse_rename(&f.attrs);
80                let skip = serde_attr::is_skipped(&f.attrs);
81                let has_default = serde_attr::has_default(&f.attrs);
82                Some(FieldDef {
83                    name,
84                    ty,
85                    rename,
86                    skip,
87                    has_default,
88                })
89            })
90            .collect(),
91        _ => vec![],
92    }
93}