1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, Attribute, DeriveInput};
6
7#[proc_macro_derive(Columnar, attributes(columnar))]
8pub fn derive(input: TokenStream) -> TokenStream {
9
10 let ast = parse_macro_input!(input as DeriveInput);
11 let name = &ast.ident;
12
13 let attr = extract_attr(&ast.attrs);
14
15 match ast.data {
16 syn::Data::Struct(data_struct) => {
17 match data_struct.fields {
18 syn::Fields::Unit => derive_unit_struct(name, &ast.generics, ast.vis, attr),
19 _ => derive_struct(name, &ast.generics, data_struct, ast.vis, attr),
20 }
21 }
22 syn::Data::Enum(data_enum) => {
23 derive_enum(name, &ast.generics, data_enum, ast.vis, attr)
24 }
25 syn::Data::Union(_) => unimplemented!("Unions are unsupported by Columnar"),
26 }
27}
28
29fn extract_attr(attrs: &[Attribute]) -> Option<proc_macro2::TokenStream> {
30 for attr in attrs {
31 if attr.path().is_ident("columnar") {
32 return Some(attr.parse_args().unwrap());
33 }
34 }
35 None
36}
37
38fn derive_struct(name: &syn::Ident, generics: &syn::Generics, data_struct: syn::DataStruct, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
39
40 let c_name = format!("{}Container", name);
41 let c_ident = syn::Ident::new(&c_name, name.span());
42
43 let r_name = format!("{}Reference", name);
44 let r_ident = syn::Ident::new(&r_name, name.span());
45
46 let named = match &data_struct.fields {
47 syn::Fields::Named(_) => true,
48 syn::Fields::Unnamed(_) => false,
49 _ => unimplemented!(),
50 };
51
52 let names: &Vec<_> = &match &data_struct.fields {
53 syn::Fields::Named(fields) => fields.named.iter().map(|field| field.ident.clone().unwrap()).collect(),
54 syn::Fields::Unnamed(fields) => (0 .. fields.unnamed.len()).map(|index| syn::Ident::new(&format!("f{}", index), name.span())).collect(),
55 _ => unimplemented!(),
56 };
57
58 let types: &Vec<_> = &match &data_struct.fields {
59 syn::Fields::Named(fields) => fields.named.iter().map(|field| &field.ty).collect(),
60 syn::Fields::Unnamed(fields) => fields.unnamed.iter().map(|field| &field.ty).collect(),
61 _ => unimplemented!(),
62 };
63
64 let container_types = &names.iter().enumerate().map(|(index, name)| {
66 let new_name = format!("C{}", index);
67 syn::Ident::new(&new_name, name.span())
68 }).collect::<Vec<_>>();
69
70 let container_struct = {
72 quote! {
73 #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
75 #vis struct #c_ident < #(#container_types),* >{
76 #(
77 pub #names : #container_types,
79 )*
80 }
81 }
82 };
83
84 let reference_struct = {
85
86 let reference_types = &names.iter().enumerate().map(|(index, name)| {
87 let new_name = format!("R{}", index);
88 syn::Ident::new(&new_name, name.span())
89 }).collect::<Vec<_>>();
90
91 let ty_gen = quote! { < #(#reference_types),* > };
92
93 let attr = if let Some(attr) = attr {
94 quote! { #[#attr] }
95 } else {
96 quote! {}
97 };
98
99 quote! {
100 #[derive(Copy, Clone, Debug)]
102 #attr
103 #vis struct #r_ident #ty_gen {
104 #(
105 pub #names : #reference_types,
107 )*
108 }
109 }
110 };
111
112 let partial_eq = {
113
114 let reference_types = &names.iter().enumerate().map(|(index, name)| {
115 let new_name = format!("R{}", index);
116 syn::Ident::new(&new_name, name.span())
117 }).collect::<Vec<_>>();
118
119 let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
120
121 let struct_generics = generics.params.iter();
122 let impl_gen = quote! { < #(#struct_generics,)* #(#reference_types),* > };
123
124 let where_clause = quote! { where #(#reference_types: PartialEq<#types>),* };
125
126 let destructure_self =
128 if named { quote! { let #name { #(#names),* } = other; } }
129 else { quote! { let #name ( #(#names),* ) = other; } };
130
131 quote! {
132 impl #impl_gen PartialEq<#name #ty_gen> for #r_ident < #(#reference_types),* > #where_clause {
133 fn eq(&self, other: &#name #ty_gen) -> bool {
134 #destructure_self
135 #(self.#names == *#names) &&*
136 }
137 }
138 }
139
140 };
141
142 let push_own = {
143 let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
144 let push = names.iter().map(|name| { quote! { self.#name.push(#name); } });
145
146 let struct_generics = generics.params.iter();
147 let impl_gen = quote! { < #(#struct_generics,)* #(#container_types),* > };
148
149 let where_clause2 = quote! { where #(#container_types: ::columnar::Push<#types>),* };
150
151 let destructure_self =
153 if named { quote! { let #name { #(#names),* } = item; } }
154 else { quote! { let #name ( #(#names),* ) = item; } };
155
156 quote! {
157 impl #impl_gen ::columnar::Push<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause2 {
158 fn push(&mut self, item: #name #ty_gen) {
159 #destructure_self
160 #(#push)*
161 }
162 }
163 }
164 };
165
166 let push_ref = {
167 let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
168 let push = names.iter().map(|name| { quote! { self.#name.push(#name); } });
169
170 let struct_generics = generics.params.iter();
171 let impl_gen = quote! { < 'columnar, #(#struct_generics,)* #(#container_types),* > };
172
173 let where_clause2 = quote! { where #(#container_types: ::columnar::Push<&'columnar #types>),* };
174
175 let destructure_self =
176 if named { quote! { let #name { #(#names),* } = item; } }
177 else { quote! { let #name ( #(#names),* ) = item; } };
178
179 quote! {
180 impl #impl_gen ::columnar::Push<&'columnar #name #ty_gen> for #c_ident < #(#container_types),* > #where_clause2 {
181 fn push(&mut self, item: &'columnar #name #ty_gen) {
182 #destructure_self
183 #(#push)*
184 }
185 }
186 }
187 };
188
189 let push_new = {
191
192 let reference_types = &names.iter().enumerate().map(|(index, name)| {
193 let new_name = format!("R{}", index);
194 syn::Ident::new(&new_name, name.span())
195 }).collect::<Vec<_>>();
196
197 let push = names.iter().map(|name| { quote! { self.#name.push(#name); } });
198
199 let impl_gen = quote! { < #(#container_types,)* #(#reference_types),* > };
200
201 let where_clause = quote! { where #(#container_types: ::columnar::Push<#reference_types>),* };
202
203 let index_type = quote! { #r_ident < #(#reference_types,)* > };
204 let destructure_self = quote! { let #r_ident { #(#names),* } = item; };
205
206 quote! {
207 impl #impl_gen ::columnar::Push<#index_type> for #c_ident < #(#container_types),* > #where_clause {
208 fn push(&mut self, item: #index_type) {
209 #destructure_self
210 #(#push)*
211 }
212 }
213 }
214 };
215
216 let index_own = {
217 let impl_gen = quote! { < #(#container_types),* > };
218 let ty_gen = quote! { < #(#container_types),* > };
219 let where_clause = quote! { where #(#container_types: ::columnar::Index),* };
220
221 let index_type = quote! { #r_ident < #(<#container_types as ::columnar::Index>::Ref,)* > };
222
223 quote! {
224 impl #impl_gen ::columnar::Index for #c_ident #ty_gen #where_clause {
225 type Ref = #index_type;
226 fn get(&self, index: usize) -> Self::Ref {
227 #r_ident { #(#names: self.#names.get(index),)* }
228 }
229 }
230 }
231 };
232
233 let index_ref = {
234 let impl_gen = quote! { < 'columnar, #(#container_types),* > };
235 let ty_gen = quote! { < #(#container_types),* > };
236 let where_clause = quote! { where #(&'columnar #container_types: ::columnar::Index),* };
237
238 let index_type = quote! { #r_ident < #(<&'columnar #container_types as ::columnar::Index>::Ref,)* > };
239
240 quote! {
241 impl #impl_gen ::columnar::Index for &'columnar #c_ident #ty_gen #where_clause {
242 type Ref = #index_type;
243 fn get(&self, index: usize) -> Self::Ref {
244 #r_ident { #(#names: (&self.#names).get(index),)* }
245 }
246 }
247 }
248 };
249
250 let clear = {
251
252 let impl_gen = quote! { < #(#container_types),* > };
253 let ty_gen = quote! { < #(#container_types),* > };
254 let where_clause = quote! { where #(#container_types: ::columnar::Clear),* };
255
256 quote! {
257 impl #impl_gen ::columnar::Clear for #c_ident #ty_gen #where_clause {
258 fn clear(&mut self) { #(self.#names.clear());* }
259 }
260 }
261 };
262
263 let length = {
264
265 let impl_gen = quote! { < #(#container_types),* > };
266 let ty_gen = quote! { < #(#container_types),* > };
267 let where_clause = quote! { where #(#container_types: ::columnar::Len),* };
268
269 let first_name = &names[0];
270
271 quote! {
272 impl #impl_gen ::columnar::Len for #c_ident #ty_gen #where_clause {
273 fn len(&self) -> usize {
274 self.#first_name.len()
275 }
276 }
277 }
278 };
279
280 let as_bytes = {
281
282 let impl_gen = quote! { <'a, #(#container_types),* > };
283 let ty_gen = quote! { < #(#container_types),* > };
284 let where_clause = quote! { where #(#container_types: ::columnar::AsBytes<'a>),* };
285
286 quote! {
287 impl #impl_gen ::columnar::AsBytes<'a> for #c_ident #ty_gen #where_clause {
288 #[inline(always)]
290 fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
291 let iter = None.into_iter();
292 #( let iter = iter.chain(self.#names.as_bytes()); )*
293 iter
294 }
295 }
296 }
297 };
298
299 let from_bytes = {
300
301 let impl_gen = quote! { < 'columnar, #(#container_types),* > };
302 let ty_gen = quote! { < #(#container_types),* > };
303 let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>),* };
304
305 quote! {
306 impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
307 fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
308 #(let #names = ::columnar::FromBytes::from_bytes(bytes);)*
309 Self { #(#names,)* }
310 }
311 }
312 }
313 };
314
315 let columnar_impl = {
316
317 let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
318
319 let where_clause2 = if let Some(struct_where) = where_clause {
320 let params = struct_where.predicates.iter();
321 quote! { where #(#types : ::columnar::Columnar,)* #(#params),* }
322 }
323 else {
324 quote! { where #(#types : ::columnar::Columnar,)* }
325 };
326
327 let destructure_self =
329 if named { quote! { let #name { #(#names),* } = self; } }
330 else { quote! { let #name ( #(#names),* ) = self; } };
331
332 let into_self =
334 if named { quote! { #name { #(#names: ::columnar::Columnar::into_owned(other.#names)),* } } }
335 else { quote! { #name ( #(::columnar::Columnar::into_owned(other.#names)),* ) } };
336
337 quote! {
338 impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
339 type Ref<'a> = #r_ident < #(<#types as ::columnar::Columnar>::Ref<'a>,)* > where #(#types: 'a,)*;
340 fn copy_from<'a>(&mut self, other: Self::Ref<'a>) {
341 #destructure_self
342 #( ::columnar::Columnar::copy_from(#names, other.#names); )*
343 }
344 fn into_owned<'a>(other: Self::Ref<'a>) -> Self {
345 #into_self
346 }
347 type Container = #c_ident < #(<#types as ::columnar::Columnar>::Container ),* >;
348 }
349
350 impl #impl_gen ::columnar::Container<#name #ty_gen> for #c_ident < #(<#types as ::columnar::Columnar>::Container ),* > #where_clause2 {
351 type Borrowed<'a> = #c_ident < #(<<#types as ::columnar::Columnar>::Container as ::columnar::Container<#types>>::Borrowed<'a> ),* > where #(#types: 'a,)*;
352 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
353 #c_ident {
354 #( #names: <<#types as ::columnar::Columnar>::Container as ::columnar::Container<#types>>::borrow(&self.#names), )*
355 }
356 }
357 }
358 }
359 };
360
361
362 quote! {
363
364 #container_struct
365 #reference_struct
366
367 #partial_eq
368
369 #push_own
370 #push_ref
371 #push_new
372
373 #index_own
374 #index_ref
375 #length
376 #clear
377
378 #as_bytes
379 #from_bytes
380
381 #columnar_impl
382
383 }.into()
384}
385
386fn derive_unit_struct(name: &syn::Ident, _generics: &syn::Generics, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
388
389 let c_name = format!("{}Container", name);
390 let c_ident = syn::Ident::new(&c_name, name.span());
391
392 if attr.is_some() {
393 panic!("Unit structs do not support attributes");
394 }
395
396 quote! {
397
398 #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
400 #vis struct #c_ident<CW = u64> {
401 pub count: CW,
403 }
404
405 impl ::columnar::Push<#name> for #c_ident {
406 fn push(&mut self, _item: #name) {
407 self.count += 1;
408 }
409 }
410
411 impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
412 fn push(&mut self, _item: &'columnar #name) {
413 self.count += 1;
414 }
415 }
416
417 impl<CW> ::columnar::Index for #c_ident<CW> {
418 type Ref = #name;
419 fn get(&self, index: usize) -> Self::Ref {
420 #name
421 }
422 }
423
424 impl<'columnar, CW> ::columnar::Index for &'columnar #c_ident<CW> {
425 type Ref = #name;
426 fn get(&self, index: usize) -> Self::Ref {
427 #name
428 }
429 }
430
431 impl ::columnar::Clear for #c_ident {
432 fn clear(&mut self) {
433 self.count = 0;
434 }
435 }
436
437 impl<CW: Copy+::columnar::common::index::CopyAs<u64>> ::columnar::Len for #c_ident<CW> {
438 fn len(&self) -> usize {
439 use columnar::common::index::CopyAs;
440 self.count.copy_as() as usize
441 }
442 }
443
444 impl<'a> ::columnar::AsBytes<'a> for #c_ident <&'a u64> {
445 fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
447 std::iter::once((8, bytemuck::cast_slice(std::slice::from_ref(self.count))))
448 }
449 }
450
451 impl<'columnar> ::columnar::FromBytes<'columnar> for #c_ident <&'columnar u64> {
452 fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
453 Self { count: &bytemuck::try_cast_slice(bytes.next().unwrap()).unwrap()[0] }
454 }
455 }
456
457 impl ::columnar::Columnar for #name {
458 type Ref<'a> = #name;
459 fn copy_from<'a>(&mut self, other: Self::Ref<'a>) { *self = other; }
460 fn into_owned<'a>(other: Self::Ref<'a>) -> Self { other }
461 type Container = #c_ident;
462 }
463
464 impl ::columnar::Container<#name> for #c_ident {
465 type Borrowed<'a> = #c_ident < &'a u64 >;
466 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
467 #c_ident { count: &self.count }
468 }
469 }
470
471 }.into()
472}
473
474#[allow(unused)]
477fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
478
479 if data_enum.variants.iter().all(|variant| variant.fields.is_empty()) {
480 return derive_tags(name, generics, data_enum, vis);
481 }
482
483 let c_name = format!("{}Container", name);
484 let c_ident = syn::Ident::new(&c_name, name.span());
485
486 let r_name = format!("{}Reference", name);
487 let r_ident = syn::Ident::new(&r_name, name.span());
488
489 let variants: Vec<(&syn::Ident, Vec<_>)> =
492 data_enum
493 .variants
494 .iter()
495 .map(|variant| (
496 &variant.ident,
497 variant.fields.iter().map(|field| &field.ty).collect()
498 ))
499 .collect();
500
501 assert!(variants.len() <= 256, "Too many variants for enum");
503
504 let names = &variants.iter().map(|(ident, _)| ident).collect::<Vec<_>>();
505
506 let container_types = &names.iter().enumerate().map(|(index, name)| {
508 let new_name = format!("C{}", index);
509 syn::Ident::new(&new_name, name.span())
510 }).collect::<Vec<_>>();
511
512 let container_struct = {
513 quote! {
514 #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
516 #[allow(non_snake_case)]
517 #vis struct #c_ident < #(#container_types,)* CVar = Vec<u8>, COff = Vec<u64>, >{
518 #(
519 pub #names : #container_types,
521 )*
522 pub variant: CVar,
524 pub offset: COff,
526 }
527 }
528 };
529
530 let reference_struct = {
531
532 let reference_types = &names.iter().enumerate().map(|(index, name)| {
533 let new_name = format!("R{}", index);
534 syn::Ident::new(&new_name, name.span())
535 }).collect::<Vec<_>>();
536
537 let ty_gen = quote! { < #(#reference_types),* > };
538
539 let attr = if let Some(attr) = attr {
540 quote! { #[#attr] }
541 } else {
542 quote! {}
543 };
544
545
546 quote! {
547 #[derive(Copy, Clone, Debug)]
549 #attr
550 #vis enum #r_ident #ty_gen {
551 #(
552 #names(#reference_types),
554 )*
555 }
556 }
557 };
558
559 let push_own = {
560
561 let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
562
563 let push = variants.iter().enumerate().map(|(index, (variant, types))| {
564
565 match data_enum.variants[index].fields {
566 syn::Fields::Unit => {
567 quote! {
568 #name::#variant => {
569 self.offset.push(self.#variant.len() as u64);
570 self.#variant.push(());
571 self.variant.push(#index as u8);
572 }
573 }
574 }
575 syn::Fields::Unnamed(_) => {
576 let temp_names = &types.iter().enumerate().map(|(index, _)| {
577 let new_name = format!("t{}", index);
578 syn::Ident::new(&new_name, variant.span())
579 }).collect::<Vec<_>>();
580
581 quote! {
582 #name::#variant( #(#temp_names),* ) => {
583 self.offset.push(self.#variant.len() as u64);
584 self.#variant.push((#(#temp_names),*));
585 self.variant.push(#index as u8);
586 },
587 }
588 }
589 syn::Fields::Named(_) => {
590 unimplemented!("Named fields in enum variants are not supported by Columnar");
591 }
592 }
593 });
594
595 let struct_generics = generics.params.iter();
596 let impl_gen = quote! { < #(#struct_generics,)* #(#container_types),* > };
597
598 let push_types = variants.iter().map(|(_, types)| quote! { (#(#types),*) });
599
600 let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
601
602 quote! {
603 impl #impl_gen ::columnar::Push<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
604 fn push(&mut self, item: #name #ty_gen) {
605 match item {
606 #( #push )*
607 }
608 }
609 }
610 }
611 };
612
613 let push_ref = {
614
615 let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
616
617 let push = variants.iter().enumerate().map(|(index, (variant, types))| {
618
619 match data_enum.variants[index].fields {
620 syn::Fields::Unit => {
621 quote! {
622 #name::#variant => {
623 self.offset.push(self.#variant.len() as u64);
624 self.#variant.push(());
625 self.variant.push(#index as u8);
626 }
627 }
628 }
629 syn::Fields::Unnamed(_) => {
630 let temp_names = &types.iter().enumerate().map(|(index, _)| {
631 let new_name = format!("t{}", index);
632 syn::Ident::new(&new_name, variant.span())
633 }).collect::<Vec<_>>();
634
635 quote! {
636 #name::#variant( #(#temp_names),* ) => {
637 self.offset.push(self.#variant.len() as u64);
638 self.#variant.push((#(#temp_names),*));
639 self.variant.push(#index as u8);
640 },
641 }
642 }
643 syn::Fields::Named(_) => {
644 unimplemented!("Named fields in enum variants are not supported by Columnar");
645 }
646 }
647 });
648
649 let struct_generics = generics.params.iter();
650 let impl_gen = quote! { < 'columnar, #(#struct_generics,)* #(#container_types),* > };
651
652 let push_types = variants.iter().map(|(_, types)| quote! { (#(&'columnar #types),*) });
653
654 let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
655
656 quote! {
657 impl #impl_gen ::columnar::Push<&'columnar #name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
658 fn push(&mut self, item: &'columnar #name #ty_gen) {
659 match item {
660 #( #push )*
661 }
662 }
663 }
664 }
665 };
666
667 let push_new = {
669
670 let reference_types = &names.iter().enumerate().map(|(index, name)| {
671 let new_name = format!("R{}", index);
672 syn::Ident::new(&new_name, name.span())
673 }).collect::<Vec<_>>();
674
675 let impl_gen = quote! { < #(#container_types,)* #(#reference_types),* > };
676
677 let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#reference_types>),* };
678
679 let index_type = quote! { #r_ident < #(#reference_types,)* > };
680 let numbers = (0 .. variants.len());
681
682 quote! {
683 impl #impl_gen ::columnar::Push<#index_type> for #c_ident < #(#container_types),* > #where_clause {
684 fn push(&mut self, item: #index_type) {
685 match item {
686 #(
687 #r_ident::#names(x) => {
688 self.offset.push(self.#names.len() as u64);
689 self.#names.push(x);
690 self.variant.push(#numbers as u8);
691 },
692 )*
693 }
694 }
695 }
696 }
697 };
698
699 let index_own = {
700 let impl_gen = quote! { < #(#container_types,)* CVal, COff> };
701 let ty_gen = quote! { < #(#container_types,)* CVal, COff> };
702 let where_clause = quote! { where #(#container_types: ::columnar::Index,)* CVal: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64> };
703
704 let index_type = quote! { #r_ident < #(<#container_types as ::columnar::Index>::Ref,)* > };
705
706 let numbers = (0 .. variants.len());
708
709 quote! {
710 impl #impl_gen ::columnar::Index for #c_ident #ty_gen #where_clause {
711 type Ref = #index_type;
712 fn get(&self, index: usize) -> Self::Ref {
713 match self.variant.index_as(index) as usize {
714 #( #numbers => #r_ident::#names(self.#names.get(self.offset.index_as(index) as usize)), )*
715 x => panic!("Unacceptable discriminant found: {:?}", x),
716 }
717 }
718 }
719 }
720 };
721
722 let index_ref = {
723 let impl_gen = quote! { < 'columnar, #(#container_types,)* CVal, COff> };
724 let ty_gen = quote! { < #(#container_types,)* CVal, COff> };
725 let where_clause = quote! { where #(&'columnar #container_types: ::columnar::Index,)* CVal: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64> };
726
727 let index_type = quote! { #r_ident < #(<&'columnar #container_types as ::columnar::Index>::Ref,)* > };
728
729 let numbers = (0 .. variants.len());
731
732 quote! {
733 impl #impl_gen ::columnar::Index for &'columnar #c_ident #ty_gen #where_clause {
734 type Ref = #index_type;
735 fn get(&self, index: usize) -> Self::Ref {
736 match self.variant.index_as(index) as usize {
737 #( #numbers => #r_ident::#names((&self.#names).get(self.offset.index_as(index) as usize)), )*
738 x => panic!("Unacceptable discriminant found: {:?}", x),
739 }
740 }
741 }
742 }
743 };
744
745 let clear = {
746
747 let impl_gen = quote! { < #(#container_types),* > };
748 let ty_gen = quote! { < #(#container_types),* > };
749 let where_clause = quote! { where #(#container_types: ::columnar::Clear),* };
750
751 quote! {
752 impl #impl_gen ::columnar::Clear for #c_ident #ty_gen #where_clause {
753 fn clear(&mut self) {
754 #(self.#names.clear();)*
755 self.variant.clear();
756 self.offset.clear();
757 }
758 }
759 }
760 };
761
762 let length = {
763
764 let impl_gen = quote! { < #(#container_types,)* CVar, COff> };
765 let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
766
767 quote! {
768 impl #impl_gen ::columnar::Len for #c_ident #ty_gen where CVar: ::columnar::Len {
769 fn len(&self) -> usize {
770 self.variant.len()
771 }
772 }
773 }
774 };
775
776 let as_bytes = {
777
778 let impl_gen = quote! { < 'a, #(#container_types,)* CVar, COff> };
779 let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
780 let where_clause = quote! { where #(#container_types: ::columnar::AsBytes<'a>,)* CVar: ::columnar::AsBytes<'a>, COff: ::columnar::AsBytes<'a> };
781
782 quote! {
783 impl #impl_gen ::columnar::AsBytes<'a> for #c_ident #ty_gen #where_clause {
784 #[inline(always)]
785 fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
786 let iter = None.into_iter();
787 #( let iter = iter.chain(self.#names.as_bytes()); )*
788 let iter = iter.chain(self.variant.as_bytes());
789 let iter = iter.chain(self.offset.as_bytes());
790 iter
791 }
792 }
793 }
794 };
795
796 let from_bytes = {
797
798 let impl_gen = quote! { < 'columnar, #(#container_types,)* CVar, COff> };
799 let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
800 let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>,)* CVar: ::columnar::FromBytes<'columnar>, COff: ::columnar::FromBytes<'columnar> };
801
802 quote! {
803 #[allow(non_snake_case)]
804 impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
805 fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
806 #(let #names = ::columnar::FromBytes::from_bytes(bytes);)*
807 let variant = ::columnar::FromBytes::from_bytes(bytes);
808 let offset = ::columnar::FromBytes::from_bytes(bytes);
809 Self { #(#names,)* variant, offset }
810 }
811 }
812 }
813 };
814
815 let columnar_impl = {
816
817 let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
818
819 let types = &variants.iter().flat_map(|(_, types)| types).collect::<Vec<_>>();
820
821 let where_clause2 = if let Some(enum_where) = where_clause {
822 let params = enum_where.predicates.iter();
823 quote! { where #(#types : ::columnar::Columnar,)* #(#params),* }
824 }
825 else {
826 quote! { where #(#types : ::columnar::Columnar,)* }
827 };
828
829
830 let variant_types = &variants.iter().map(|(_, types)| quote! { (#(#types),*) }).collect::<Vec<_>>();
831
832 let container_types = &variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Container }).collect::<Vec<_>>();
833
834 let reference_args = variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Ref<'a> });
835
836 let copy_from = variants.iter().enumerate().map(|(index, (variant, types))| {
838
839 if data_enum.variants[index].fields == syn::Fields::Unit {
840 quote! {
841 (#name::#variant, #r_ident::#variant(_)) => { }
842 (_, #r_ident::#variant(_)) => { *self = #name::#variant; }
843 }
844 }
845 else {
846 let temp_names1 = &types.iter().enumerate().map(|(index, _)| {
847 let new_name = format!("s{}", index);
848 syn::Ident::new(&new_name, variant.span())
849 }).collect::<Vec<_>>();
850 let temp_names2 = &types.iter().enumerate().map(|(index, _)| {
851 let new_name = format!("t{}", index);
852 syn::Ident::new(&new_name, variant.span())
853 }).collect::<Vec<_>>();
854
855 quote! {
856 (#name::#variant( #( #temp_names1 ),* ), #r_ident::#variant( ( #( #temp_names2 ),* ) )) => {
857 #( ::columnar::Columnar::copy_from(#temp_names1, #temp_names2); )*
858 }
859 }
860 }
861 }).collect::<Vec<_>>();
862
863 let into_owned = variants.iter().enumerate().map(|(index, (variant, types))| {
865
866 if data_enum.variants[index].fields == syn::Fields::Unit {
867 quote! { #r_ident::#variant(_) => #name::#variant, }
868 }
869 else {
870 let temp_names = &types.iter().enumerate().map(|(index, _)| {
871 let new_name = format!("t{}", index);
872 syn::Ident::new(&new_name, variant.span())
873 }).collect::<Vec<_>>();
874
875 quote! {
876 #r_ident::#variant(( #( #temp_names ),* )) => {
877 #name::#variant( #( ::columnar::Columnar::into_owned(#temp_names) ),* )
878 },
879 }
880 }
881 }).collect::<Vec<_>>();
882
883
884 quote! {
885 impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
886 type Ref<'a> = #r_ident < #(#reference_args,)* > where Self: 'a, #(#variant_types: 'a,)*;
887 fn copy_from<'a>(&mut self, other: Self::Ref<'a>) {
888 match (&mut *self, other) {
889 #( #copy_from )*
890 (_, other) => { *self = Self::into_owned(other); }
891 }
892 }
893 fn into_owned<'a>(other: Self::Ref<'a>) -> Self {
894 match other {
895 #( #into_owned )*
896 }
897 }
898 type Container = #c_ident < #(#container_types),* >;
899 }
900
901 impl #impl_gen ::columnar::Container<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause2 {
902 type Borrowed<'a> = #c_ident < #( < #container_types as ::columnar::Container<#variant_types> >::Borrowed<'a>, )* &'a [u8], &'a [u64] > where #(#variant_types: 'a,)*;
903 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
904 #c_ident {
905 #(#names: self.#names.borrow(),)*
906 variant: self.variant.borrow(),
907 offset: self.offset.borrow(),
908 }
909 }
910 }
911 }
912 };
913
914 quote! {
915
916 #container_struct
917 #reference_struct
918
919 #push_own
920 #push_ref
921 #push_new
922
923 #index_own
924 #index_ref
925 #length
926 #clear
927
928 #as_bytes
929 #from_bytes
930
931 #columnar_impl
932
933 }.into()
934}
935
936#[allow(unused)]
938fn derive_tags(name: &syn::Ident, _generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility) -> proc_macro::TokenStream {
939
940 let c_name = format!("{}Container", name);
941 let c_ident = syn::Ident::new(&c_name, name.span());
942
943 let names: Vec<&syn::Ident> =
944 data_enum
945 .variants
946 .iter()
947 .map(|variant| &variant.ident)
948 .collect();
949
950 let indices: &Vec<u8> = &(0 .. names.len()).map(|x| x as u8).collect();
951
952 assert!(names.len() <= 256, "Too many variants for enum");
954
955 quote! {
956 #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
958 #vis struct #c_ident <CVar = Vec<u8>> {
959 pub variant: CVar,
961 }
962
963 impl ::columnar::Push<#name> for #c_ident {
964 fn push(&mut self, item: #name) {
965 match item {
966 #( #name::#names => self.variant.push(#indices), )*
967 }
968 }
969 }
970
971 impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
972 fn push(&mut self, item: &'columnar #name) {
973 match *item {
974 #( #name::#names => self.variant.push(#indices), )*
975 }
976 }
977 }
978
979 impl<CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for #c_ident <CVar> {
980 type Ref = #name;
981 fn get(&self, index: usize) -> Self::Ref {
982 match self.variant.index_as(index) {
983 #( #indices => #name::#names, )*
984 x => panic!("Unacceptable discriminant found: {:?}", x),
985 }
986 }
987 }
988
989 impl<'columnar, CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for &'columnar #c_ident <CVar> {
990 type Ref = #name;
991 fn get(&self, index: usize) -> Self::Ref {
992 match self.variant.index_as(index) {
993 #( #indices => #name::#names, )*
994 x => panic!("Unacceptable discriminant found: {:?}", x),
995 }
996 }
997 }
998
999 impl<CVar: ::columnar::Clear> ::columnar::Clear for #c_ident <CVar> {
1000 fn clear(&mut self) {
1001 self.variant.clear();
1002 }
1003 }
1004
1005 impl<CVar: ::columnar::Len> ::columnar::Len for #c_ident <CVar> {
1006 fn len(&self) -> usize {
1007 self.variant.len()
1008 }
1009 }
1010
1011 impl<'a, CVar: ::columnar::AsBytes<'a>> ::columnar::AsBytes<'a> for #c_ident <CVar> {
1012 #[inline(always)]
1014 fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
1015 self.variant.as_bytes()
1016 }
1017 }
1018
1019 impl<'columnar, CVar: ::columnar::FromBytes<'columnar>> ::columnar::FromBytes<'columnar> for #c_ident <CVar> {
1020 fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
1021 Self { variant: ::columnar::FromBytes::from_bytes(bytes) }
1022 }
1023 }
1024
1025 impl ::columnar::Columnar for #name {
1026 type Ref<'a> = #name;
1027 fn copy_from<'a>(&mut self, other: Self::Ref<'a>) { *self = other; }
1028 fn into_owned<'a>(other: Self::Ref<'a>) -> Self { other }
1029 type Container = #c_ident;
1030 }
1031
1032 impl<CV: ::columnar::Container<u8>> ::columnar::Container<#name> for #c_ident <CV> {
1033 type Borrowed<'a> = #c_ident < CV::Borrowed<'a> > where CV: 'a;
1034 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
1035 #c_ident {
1036 variant: self.variant.borrow()
1037 }
1038 }
1039 }
1040 }.into()
1041}