vercel_rpc_cli/parser/
types.rs1use syn::{Fields, FieldsNamed, Type};
2
3use crate::model::RustType;
4
5pub fn extract_rust_type(ty: &Type) -> RustType {
10 match ty {
11 Type::Path(type_path) => {
12 let segment = type_path
13 .path
14 .segments
15 .last()
16 .expect("Type::Path always has at least one segment");
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<(String, RustType)> {
72 match fields {
73 Fields::Named(FieldsNamed { named, .. }) => named
74 .iter()
75 .filter_map(|f| {
76 let name = f.ident.as_ref()?.to_string();
77 let ty = extract_rust_type(&f.ty);
78 Some((name, ty))
79 })
80 .collect(),
81 _ => vec![],
82 }
83}