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}