metaxy_cli/parser/
types.rs1use syn::{Fields, FieldsNamed, FieldsUnnamed, 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 segments = &type_path.path.segments;
14 if segments.is_empty() {
15 let token_str = quote::quote!(#ty).to_string();
16 return RustType::simple(token_str);
17 }
18 let name = segments
20 .iter()
21 .map(|s| s.ident.to_string())
22 .collect::<Vec<_>>()
23 .join("::");
24 let generics =
25 extract_generic_args(&segments.last().expect("non-empty segments").arguments);
26
27 if generics.is_empty() {
28 RustType::simple(name)
29 } else {
30 RustType::with_generics(name, generics)
31 }
32 }
33
34 Type::Reference(type_ref) => extract_rust_type(&type_ref.elem),
35
36 Type::Tuple(tuple) => {
37 if tuple.elems.is_empty() {
38 RustType::simple("()")
39 } else {
40 let inner: Vec<RustType> = tuple.elems.iter().map(extract_rust_type).collect();
41 RustType::with_generics("tuple", inner)
42 }
43 }
44
45 Type::Array(array) => {
46 let elem = extract_rust_type(&array.elem);
47 RustType::with_generics("Array", vec![elem])
48 }
49
50 Type::Slice(slice) => {
51 let elem = extract_rust_type(&slice.elem);
52 RustType::with_generics("Array", vec![elem])
53 }
54
55 _ => {
56 let token_str = quote::quote!(#ty).to_string();
57 RustType::simple(token_str)
58 }
59 }
60}
61
62fn extract_generic_args(arguments: &syn::PathArguments) -> Vec<RustType> {
64 match arguments {
65 syn::PathArguments::AngleBracketed(args) => args
66 .args
67 .iter()
68 .filter_map(|arg| match arg {
69 syn::GenericArgument::Type(ty) => Some(extract_rust_type(ty)),
70 _ => None,
71 })
72 .collect(),
73 _ => vec![],
74 }
75}
76
77pub fn extract_tuple_fields(fields: &Fields) -> Vec<RustType> {
81 match fields {
82 Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
83 unnamed.iter().map(|f| extract_rust_type(&f.ty)).collect()
84 }
85 _ => vec![],
86 }
87}
88
89pub fn extract_struct_fields(fields: &Fields) -> Vec<FieldDef> {
92 match fields {
93 Fields::Named(FieldsNamed { named, .. }) => named
94 .iter()
95 .filter_map(|f| {
96 let name = f.ident.as_ref()?.to_string();
97 let ty = extract_rust_type(&f.ty);
98 let rename = serde_attr::parse_rename(&f.attrs);
99 let skip = serde_attr::is_skipped(&f.attrs);
100 let has_default = serde_attr::has_default(&f.attrs);
101 let flatten = serde_attr::is_flattened(&f.attrs);
102 Some(FieldDef {
103 name,
104 ty,
105 rename,
106 skip,
107 has_default,
108 flatten,
109 })
110 })
111 .collect(),
112 _ => vec![],
113 }
114}