saa_proto_core/
lib.rs

1mod utils;
2use quote::{ToTokens, quote};
3use proc_macro::TokenStream;
4use syn::{parse_macro_input, parse_quote, DeriveInput};
5use utils::{fallible_macro, Options};
6
7
8fn strum_enum(input: &DeriveInput) -> proc_macro2::TokenStream {
9    let ident = &input.ident;
10    quote! {
11        #[derive(
12            Clone, Debug, PartialEq,
13            ::saa_schema::strum_macros::Display,
14            ::saa_schema::strum_macros::EnumDiscriminants,
15            ::saa_schema::strum_macros::VariantNames
16        )]
17        #[strum_discriminants(
18            derive(
19                ::saa_schema::strum_macros::Display,
20                ::saa_schema::strum_macros::EnumString,
21                ::saa_schema::strum_macros::VariantArray,
22                ::saa_schema::strum_macros::AsRefStr
23            ),
24            strum(serialize_all = "snake_case", crate = "::saa_schema::strum")
25        )]
26        #[strum(serialize_all = "snake_case", crate = "::saa_schema::strum")]
27        #[allow(clippy::derive_partial_eq_without_eq)]
28        #input
29
30        impl ::saa_schema::strum::IntoDiscriminant for Box<#ident> {
31            type Discriminant = <#ident as ::saa_schema::strum::IntoDiscriminant>::Discriminant;
32            fn discriminant(&self) -> Self::Discriminant {
33                (*self).discriminant()
34            }
35        }
36    }
37}
38
39
40
41
42#[proc_macro_attribute]
43pub fn saa_type(
44    _attr: TokenStream,
45    input: TokenStream,
46) -> TokenStream {
47    let input_ast = parse_macro_input!(input as DeriveInput);
48    match &input_ast.data {
49        syn::Data::Struct(_) => {
50            quote! {
51                #[derive(Clone, Debug, PartialEq)]
52                #[allow(clippy::derive_partial_eq_without_eq)]
53                #input_ast
54            }.into()
55        },
56        syn::Data::Enum(_) => {
57            quote! {
58                #[derive(Clone, Debug, PartialEq)]
59                #[allow(clippy::derive_partial_eq_without_eq)]
60                #input_ast
61            }.into()
62        },
63        syn::Data::Union(_) => panic!("unions are not supported"),
64    }
65}
66
67
68
69fallible_macro! {
70    #[proc_macro_attribute]
71    pub fn saa_error(
72        attr: proc_macro::TokenStream,
73        input: proc_macro::TokenStream,
74    ) -> syn::Result<proc_macro::TokenStream> {
75        let options = syn::parse(attr)?;
76        let input = syn::parse(input)?;
77        let expanded = saa_error_impl(input, options)?;
78        Ok(expanded.into_token_stream().into())
79    }
80}
81
82
83
84fn saa_error_impl(input: DeriveInput, options: Options) -> syn::Result<DeriveInput> {
85    let crate_path = &options.crate_path;
86    let error_path: syn::Path = syn::parse_quote!(#crate_path::thiserror::Error);
87    let mut stream = quote! {
88        #[derive(PartialEq, Debug, #error_path)]
89    };
90    match &input.data {
91        syn::Data::Enum(_) => {},
92        _ => return Err(syn::Error::new_spanned(&input, "Only enums are supported")),
93    };
94    stream.extend(input.to_token_stream());
95    syn::parse2(stream)
96}
97
98
99
100#[proc_macro_attribute]
101pub fn saa_derivable(
102    _attr: TokenStream,
103    input: TokenStream,
104) -> TokenStream {
105    let input_ast = parse_macro_input!(input as DeriveInput);
106    match &input_ast.data {
107        syn::Data::Struct(_) => {
108            quote! {
109                #[derive(Clone, Debug, PartialEq)]
110                #[allow(clippy::derive_partial_eq_without_eq)]
111                #input_ast
112            }.into()
113        },
114        syn::Data::Enum(_) => {
115            strum_enum(&input_ast).into()
116        },
117        syn::Data::Union(_) => panic!("unions are not supported"),
118    }
119}
120
121
122
123
124#[proc_macro_attribute]
125pub fn saa_str_struct(
126    _attr: proc_macro::TokenStream,
127    input: proc_macro::TokenStream,
128) -> proc_macro::TokenStream {
129    let input = parse_macro_input!(input as DeriveInput);
130
131    let expanded : DeriveInput = match input.data {
132        syn::Data::Struct(_) => parse_quote! {
133            #[derive(Copy, Clone, Debug, Eq, PartialOrd, Ord, Default)]
134            #input 
135        },
136        syn::Data::Enum(_) => panic!("enums are not supported"),
137        syn::Data::Union(_) => panic!("unions are not supported"),
138    };
139
140    let stream = expanded.into_token_stream();
141
142    proc_macro::TokenStream::from(stream)
143}