Skip to main content

vercel_rpc_cli/parser/
types.rs

1use syn::{Fields, FieldsNamed, Type};
2
3use crate::model::RustType;
4
5/// Converts a `syn::Type` into our `RustType` representation.
6///
7/// Handles paths (simple and generic), references, tuples, arrays, and unit.
8/// Unknown or unsupported types fall back to their token representation.
9pub 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
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 definition into `(name, RustType)` pairs.
71pub 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}