vercel_rpc_cli/parser/
types.rs1use syn::{Fields, FieldsNamed, Type};
2
3use super::serde as serde_attr;
4use crate::model::{FieldDef, RustType};
5
6pub 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
55fn 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
70pub 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}