1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{DeriveInput, Index};
4
5#[proc_macro_derive(Bytes)]
6pub fn derive_bytes(input: TokenStream) -> TokenStream {
7 let input = syn::parse_macro_input!(input as DeriveInput);
8
9 let ident = input.ident;
10 let generics = input.generics;
11
12 let mut gen_where = quote!();
13
14 {
15 let mut gen = Vec::new();
16 for generig in generics.type_params() {
17 gen.push(quote!(#generig: TBytes))
18 }
19
20 if !gen.is_empty() {
21 gen_where = quote! {
22 where #(#gen),*
23 }
24 }
25 }
26
27 match input.data {
28 syn::Data::Struct(s) => {
29 let mut names = Vec::with_capacity(s.fields.len());
30 let mut types = Vec::with_capacity(s.fields.len());
31
32 for field in s.fields {
33 if let Some(ident) = field.ident {
34 names.push(ident);
35 }
36
37 types.push(field.ty);
38 }
39
40 if !names.is_empty() {
41 let mut from_bytes_blocks = Vec::new();
42
43 for (i, (name, type_)) in names.iter().zip(types.iter()).enumerate() {
44 let mut before_names = Vec::new();
45 for name in names[0..i].iter().rev() {
46 before_names.push(name);
47 }
48 from_bytes_blocks.push(quote! {
49 let #name = if let Some(value) = <#type_>::from_bytes(buffer) {value}else{
50 #(
51 let mut bytes = #before_names.to_bytes();
52 while let Some(byte) = bytes.pop(){
53 buffer.insert(0, byte);
54 }
55 )*
56 return None;
57 };
58 });
59 }
60
61 quote! {
62 #[allow(clippy::question_mark)]
63 impl #generics TBytes for #ident #generics #gen_where{
64 fn size(&self) -> usize{
65 #(self.#names.size())+*
66 }
67
68 fn to_bytes(&self) -> Vec<u8>{
69 let mut buffer = Vec::with_capacity(self.size());
70
71 #(buffer.append(&mut self.#names.to_bytes());)*
72
73 buffer
74 }
75
76 fn from_bytes(buffer: &mut TBuffer) -> Option<Self>{
77 #(#from_bytes_blocks)*
78 Some(Self{
79 #(#names),*
80 })
81 }
82 }
83 }
84 .into()
85 } else {
86 let nums = (0usize..types.len())
87 .map(Index::from)
88 .collect::<Vec<Index>>();
89 let names = nums
90 .iter()
91 .map(|n| format_ident!("v{}", n))
92 .collect::<Vec<proc_macro2::Ident>>();
93
94 let mut from_bytes_blocks = Vec::new();
95
96 for (i, (name, type_)) in names.iter().zip(types.iter()).enumerate() {
97 let mut before_names = Vec::new();
98 for name in names[0..i].iter().rev() {
99 before_names.push(name);
100 }
101 from_bytes_blocks.push(quote! {
102 let #name = if let Some(value) = <#type_>::from_bytes(buffer) {value}else{
103 #(
104 let mut bytes = #before_names.to_bytes();
105 while let Some(byte) = bytes.pop(){
106 buffer.insert(0, byte);
107 }
108 )*
109 return None;
110 };
111 });
112 }
113
114 quote! {
115 #[allow(clippy::question_mark)]
116 impl #generics TBytes for #ident #generics #gen_where{
117 fn size(&self) -> usize{
118 #(self.#nums.size())+*
119 }
120
121 fn to_bytes(&self) -> Vec<u8>{
122 let mut buffer = Vec::with_capacity(self.size());
123
124 #(buffer.append(&mut self.#nums.to_bytes());)*
125
126 buffer
127 }
128
129 fn from_bytes(buffer: &mut TBuffer) -> Option<Self>{
130 #(#from_bytes_blocks)*
131 Some(Self(
132 #(#names),*
133 ))
134 }
135 }
136 }
137 .into()
138 }
139 }
140 syn::Data::Enum(e) => {
141 let mut idxs = Vec::new();
144 let mut idents = Vec::new();
147 let mut fields = Vec::new();
149
150 for (i, variant) in e.variants.iter().enumerate() {
151 idxs.push(i);
152 idents.push(&variant.ident);
153 fields.push(&variant.fields);
154 }
155
156 let mut variant_from = Vec::new();
159
160 let mut variant_to = Vec::new();
162 let mut variants = Vec::new();
164 let mut variant_size = Vec::new();
167
168 for i in 0..idents.len() {
169 let ident = idents[i].clone();
170 let fields = fields[i].clone();
171
172 let mut variant_init_vars = Vec::new();
174 let mut variant_vars = Vec::new();
176
177 let mut is_object = false;
178 for (ii, field) in fields.iter().enumerate() {
179 let ty = field.ty.clone();
180 if let Some(ident) = field.ident.clone() {
181 is_object = true;
182 variant_init_vars.push(quote!(
183 #ident : <#ty>::from_bytes(buffer)?
184 ));
185 variant_vars.push(quote!(
186 #ident
187 ));
188 } else {
189 variant_init_vars.push(quote!(
190 <#ty>::from_bytes(buffer)?
191 ));
192 let vii = format_ident!("v{}", ii);
193 variant_vars.push(quote!(#vii));
194 }
195 }
196 if !variant_vars.is_empty() {
197 if is_object {
198 variants.push(quote!(#ident{#(#variant_vars),*}));
199 } else {
200 variants.push(quote!(#ident(#(#variant_vars),*)));
201 }
202 variant_to.push(quote! {
203 #(buffer.append(&mut #variant_vars.to_bytes());)*
204 });
205 variant_size.push(quote! {
206 #(#variant_vars.size())+*
207 });
208 } else {
209 variants.push(quote! {
210 #ident
211 });
212 variant_to.push(quote! {});
213 variant_size.push(quote! {0});
214 }
215 if !variant_init_vars.is_empty() {
216 let vars = if is_object {
217 fields
218 .iter()
219 .map(|f| f.ident.clone().unwrap())
220 .collect::<Vec<_>>()
221 } else {
222 (0..fields.len())
223 .map(|f| format_ident!("f{f}"))
224 .collect::<Vec<_>>()
225 };
226 let mut from_bytes_var = Vec::new();
227 for (i, field) in fields.iter().enumerate() {
228 let ty = &field.ty;
229 let before = vars[0..i].iter().rev().collect::<Vec<_>>();
230 from_bytes_var.push(quote! {
231 if let Some(value) = <#ty>::from_bytes(buffer) {value}else{
232 #(
233 let mut bytes = #before.to_bytes();
234 while let Some(byte) = bytes.pop(){
235 buffer.insert(0, byte);
236 }
237 )*
238 let mut bytes = id.to_bytes();
239 while let Some(byte) = bytes.pop(){
240 buffer.insert(0, byte);
241 }
242
243 return None;
244 }
245 });
246 }
247 if is_object {
248 variant_from.push(quote! {
249 {
250 #(let #vars = #from_bytes_var;)*
251 return Some(Self::#ident{#(#vars),*})
252 }
253 });
254 } else {
255 variant_from.push(quote! {
256 {
257 #(let #vars = #from_bytes_var;)*
258 return Some(Self::#ident(#(#vars),*))
259 }
260 });
261 }
262 } else {
263 variant_from.push(quote! {
264 return Some(Self::#ident)
265 });
266 }
267 }
268
269 quote! {
270 #[allow(clippy::question_mark)]
271 impl #generics TBytes for #ident #generics #gen_where{
272 fn size(&self) -> usize{
273 (match self{
274 #(Self::#variants => #variant_size),*
275 } + 0usize.size())
276 }
277
278 fn to_bytes(&self) -> Vec<u8>{
279 let mut buffer = Vec::new();
280
281 match self{
282 #(Self::#variants => {buffer.append(&mut #idxs.to_bytes()); #variant_to}),*
283 };
284
285 buffer
286 }
287
288 fn from_bytes(buffer: &mut TBuffer) -> Option<Self>{
289 let id = usize::from_bytes(buffer)?;
290
291 match id{
292 #(#idxs => #variant_from,)*
293 _=> {
294 let mut bytes = id.to_bytes();
295 while let Some(byte) = bytes.pop(){
296 buffer.insert(0, byte);
297 }
298 None
299 }
300 }
301 }
302 }
303 }
304 .into()
305 }
306 syn::Data::Union(_) => todo!(),
307 }
308}