schema_bridge_macro/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput, Fields, Ident};
4
5#[proc_macro_derive(SchemaBridge, attributes(serde))]
6pub fn derive_schema_bridge(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
8 let name = input.ident;
9
10 let ts_impl = impl_to_ts(&name, &input.data);
11 let schema_impl = impl_to_schema(&name, &input.data);
12
13 let expanded = quote! {
14 impl ::schema_bridge::SchemaBridge for #name {
15 fn to_ts() -> String {
16 #ts_impl
17 }
18
19 fn to_schema() -> ::schema_bridge::Schema {
20 #schema_impl
21 }
22 }
23 };
24
25 TokenStream::from(expanded)
26}
27
28fn impl_to_ts(_name: &Ident, data: &Data) -> proc_macro2::TokenStream {
29 match data {
30 Data::Struct(data) => {
31 match &data.fields {
32 Fields::Named(fields) => {
33 let fields_ts = fields.named.iter().map(|f| {
34 let field_name = &f.ident;
35 let ty = &f.ty;
36 quote! {
37 format!("{}: {};", stringify!(#field_name), <#ty as ::schema_bridge::SchemaBridge>::to_ts())
38 }
39 });
40
41 quote! {
42 let fields = vec![#(#fields_ts),*];
43 format!("{{ {} }}", fields.join(" "))
44 }
45 }
46 Fields::Unnamed(fields) => {
47 if fields.unnamed.len() == 1 {
49 let inner_ty = &fields.unnamed[0].ty;
51 quote! {
52 <#inner_ty as ::schema_bridge::SchemaBridge>::to_ts()
53 }
54 } else {
55 let field_types = fields.unnamed.iter().map(|f| {
57 let ty = &f.ty;
58 quote! {
59 <#ty as ::schema_bridge::SchemaBridge>::to_ts()
60 }
61 });
62
63 quote! {
64 let types = vec![#(#field_types),*];
65 format!("[{}]", types.join(", "))
66 }
67 }
68 }
69 Fields::Unit => quote! { "null".to_string() },
70 }
71 }
72 Data::Enum(data) => {
73 let variants = data.variants.iter().map(|v| {
74 let variant_name = &v.ident;
75 quote! {
77 format!("'{}'", stringify!(#variant_name))
78 }
79 });
80
81 quote! {
82 let variants = vec![#(#variants),*];
83 variants.join(" | ")
84 }
85 }
86 _ => quote! { "any".to_string() },
87 }
88}
89
90fn impl_to_schema(_name: &Ident, _data: &Data) -> proc_macro2::TokenStream {
91 quote! {
93 ::schema_bridge::Schema::Any
94 }
95}