1extern crate proc_macro;
2
3use bitsy_utils::type_id;
4use proc_macro::TokenStream;
5use proc_macro_error::proc_macro_error;
6use quote::{format_ident, quote};
7use syn::{parse_macro_input, Ident, ItemFn, ItemStruct};
8
9fn process_task(attrs: TokenStream, input: TokenStream) -> TokenStream {
10 let func = parse_macro_input!(input as ItemFn);
11 let ident = format_ident!("{}Task", parse_macro_input!(attrs as Ident));
12
13 let output = quote! {
14
15 struct #ident{}
16
17 #[async_trait::async_trait]
18 impl<K, D> Task<K, D> for #ident
19 where
20 K: DatabaseKey,
21 D: Database + Send + Sync + 'static
22 {
23 type Database = D;
24 #func
25 }
26
27 };
28
29 TokenStream::from(output)
30}
31
32fn process_key(input: TokenStream) -> TokenStream {
33 let item = parse_macro_input!(input as ItemStruct);
34 let ident = &item.ident;
35 let name = ident.to_string();
36 let ty_id = type_id(&*name);
38
39 let output = quote! {
40
41 #[derive(Debug, PartialEq, Eq, Hash, Clone)]
42 #item
43
44 impl DatabaseKey for #ident {}
45
46 impl Key for #ident {
47
48 const NAME: &'static str = #name;
49 const TYPE_ID: usize = #ty_id;
50
51 type Item = Field;
52 type Metadata = KeyMetadata;
53
54 fn builder() -> Self {
55 Self {
56 fields: Vec::new(),
57 metadata: KeyMetadata::default(),
58 }
59 }
60
61 fn metadata(&mut self, meta: KeyMetadata) -> &mut Self {
62 self.metadata = KeyMetadata::with_key_code(meta, Self::TYPE_ID);
63 self
64 }
65
66 fn field(&mut self, f: Self::Item) -> &mut Self {
67 self.fields.push(f);
68 self
69 }
70
71 fn build(&self) -> Self {
72 self.clone()
73 }
74
75 fn flatten(&self) -> Bytes {
76 let fields = Bytes::from(
77 self.fields
78 .iter()
79 .map(|f| usize::to_le_bytes(f.type_id).to_vec())
80 .collect::<Vec<Vec<u8>>>()
81 .into_iter()
82 .flatten()
83 .collect::<Vec<u8>>(),
84 );
85
86 let id = Bytes::from(usize::to_le_bytes(Self::TYPE_ID).to_vec());
87 Bytes::from([id, fields].concat())
88 }
90
91 fn get_metadata(&self) -> Self::Metadata {
92 self.metadata.clone()
93 }
94
95 fn type_id(&self) -> usize {
96 Self::TYPE_ID
97 }
98
99 fn name(&self) -> &'static str {
100 Self::NAME
101 }
102 }
103
104 impl AsBytes for #ident {
105 fn as_bytes(&self) -> &[u8] {
106 <#ident as AsBytes>::as_bytes(self)
107 }
108 }
109
110 impl #ident {
111 pub fn from_input(value: Input, extractors: &Extractors, metadata: &Metadata) -> BitsyResult<Self> {
112 let meta = metadata.get(&Self::TYPE_ID);
113 let fields = extractors.items.iter().map(|e| e.1.call(&value).expect("Failed to call on input.")).collect::<Vec<Field>>();
114
115 Ok(#ident{ fields, metadata: meta.to_owned() })
117 }
118
119 pub fn from_bytes(b: Bytes, metadata: &Metadata) -> BitsyResult<#ident> {
120 let mut parts = b.chunks_exact(64);
121
122 let key_ty_id = parts.next().unwrap();
123 let meta = metadata.get(&Self::TYPE_ID);
124
125 Ok(#ident::builder())
128 }
129 }
130
131
132 };
133
134 TokenStream::from(output)
135}
136
137#[proc_macro_error]
138#[proc_macro_attribute]
139pub fn task(attrs: TokenStream, input: TokenStream) -> TokenStream {
140 process_task(attrs, input)
141}
142
143#[proc_macro_error]
144#[proc_macro_attribute]
145pub fn key(_attrs: TokenStream, input: TokenStream) -> TokenStream {
146 process_key(input)
147}