barter_macro/
lib.rs

1extern crate proc_macro;
2
3use convert_case::{Boundary, Case, Casing};
4use proc_macro::TokenStream;
5use quote::quote;
6use syn::DeriveInput;
7
8#[proc_macro_derive(DeExchange)]
9pub fn de_exchange_derive(input: TokenStream) -> TokenStream {
10    // Parse Rust code abstract syntax tree with Syn from TokenStream -> DeriveInput
11    let ast: DeriveInput =
12        syn::parse(input).expect("de_exchange_derive() failed to parse input TokenStream");
13
14    // Determine execution name
15    let exchange = &ast.ident;
16
17    let generated = quote! {
18        impl<'de> serde::Deserialize<'de> for #exchange {
19            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
20            where
21                D: serde::de::Deserializer<'de>
22            {
23                let input = <String as serde::Deserialize>::deserialize(deserializer)?;
24                let exchange = #exchange::ID;
25                let expected = exchange.as_str();
26
27                if input.as_str() == expected {
28                    Ok(Self::default())
29                } else {
30                    Err(serde::de::Error::invalid_value(
31                        serde::de::Unexpected::Str(input.as_str()),
32                        &expected
33                    ))
34                }
35            }
36        }
37    };
38
39    TokenStream::from(generated)
40}
41
42#[proc_macro_derive(SerExchange)]
43pub fn ser_exchange_derive(input: TokenStream) -> TokenStream {
44    // Parse Rust code abstract syntax tree with Syn from TokenStream -> DeriveInput
45    let ast: DeriveInput =
46        syn::parse(input).expect("ser_exchange_derive() failed to parse input TokenStream");
47
48    // Determine Exchange
49    let exchange = &ast.ident;
50
51    let generated = quote! {
52        impl serde::Serialize for #exchange {
53            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
54            where
55                S: serde::ser::Serializer,
56            {
57                serializer.serialize_str(#exchange::ID.as_str())
58            }
59        }
60    };
61
62    TokenStream::from(generated)
63}
64
65#[proc_macro_derive(DeSubKind)]
66pub fn de_sub_kind_derive(input: TokenStream) -> TokenStream {
67    // Parse Rust code abstract syntax tree with Syn from TokenStream -> DeriveInput
68    let ast: DeriveInput =
69        syn::parse(input).expect("de_sub_kind_derive() failed to parse input TokenStream");
70
71    // Determine SubKind name
72    let sub_kind = &ast.ident;
73
74    let expected_sub_kind = sub_kind
75        .to_string()
76        .from_case(Case::Pascal)
77        .without_boundaries(&Boundary::letter_digit())
78        .to_case(Case::Snake);
79
80    let generated = quote! {
81        impl<'de> serde::Deserialize<'de> for #sub_kind {
82            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
83            where
84                D: serde::de::Deserializer<'de>
85            {
86                let input = <String as serde::Deserialize>::deserialize(deserializer)?;
87
88                if input == #expected_sub_kind {
89                    Ok(Self)
90                } else {
91                    Err(serde::de::Error::invalid_value(
92                        serde::de::Unexpected::Str(input.as_str()),
93                        &#expected_sub_kind
94                    ))
95                }
96            }
97        }
98    };
99
100    TokenStream::from(generated)
101}
102
103#[proc_macro_derive(SerSubKind)]
104pub fn ser_sub_kind_derive(input: TokenStream) -> TokenStream {
105    // Parse Rust code abstract syntax tree with Syn from TokenStream -> DeriveInput
106    let ast: DeriveInput =
107        syn::parse(input).expect("ser_sub_kind_derive() failed to parse input TokenStream");
108
109    // Determine SubKind name
110    let sub_kind = &ast.ident;
111    let sub_kind_string = sub_kind.to_string().to_case(Case::Snake);
112    let sub_kind_str = sub_kind_string.as_str();
113
114    let generated = quote! {
115        impl serde::Serialize for #sub_kind {
116            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
117            where
118                S: serde::ser::Serializer,
119            {
120                serializer.serialize_str(#sub_kind_str)
121            }
122        }
123    };
124
125    TokenStream::from(generated)
126}