columnar_derive/
lib.rs

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    // Generic type parameters for the containers for the struct fields.
65    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    // The container struct is a tuple of containers, named to correspond with fields.
71    let container_struct = {
72        quote! {
73            /// Derived columnar container for a struct.
74            #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
75            #vis struct #c_ident < #(#container_types),* >{
76                #(
77                    /// Container for #names.
78                    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            /// Derived columnar reference for a struct.
101            #[derive(Copy, Clone, Debug)]
102            #attr
103            #vis struct #r_ident #ty_gen {
104                #(
105                    /// Field for #names.
106                    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        // Either use curly braces or parentheses to destructure the item.
127        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        // Either use curly braces or parentheses to destructure the item.
152        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    // Implementation of `Push<#r_ident>`
190    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                // type Borrowed<'columnar> = #c_ident < #(<#container_types as ::columnar::AsBytes>::Borrowed<'columnar>,)*>;
289                #[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        // Either use curly braces or parentheses to destructure the item.
328        let destructure_self = 
329        if named { quote! { let #name { #(#names),* } = self; } }
330        else     { quote! { let #name ( #(#names),* ) = self; } };
331        
332        // Either use curly braces or parentheses to destructure the item.
333        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
386// TODO: Do we need to use the generics?
387fn 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        /// Derived columnar container for a unit struct.
399        #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
400        #vis struct #c_ident<CW = u64> {
401            /// Count of the number of contained records.
402            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            // type Borrowed<'columnar> = #c_ident;
446            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/// The derived container for an `enum` type will be a struct with containers for each field of each variant, plus an offset container and a discriminant container.
475/// Its index `Ref` type will be an enum with parallel variants, each containing the index `Ref` types of the corresponding variant containers.
476#[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    // Record everything we know about the variants.
490    // TODO: Distinguish between unit and 0-tuple variants.
491    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    // Bit silly, but to help us fit in a byte and reign in bloat.
502    assert!(variants.len() <= 256, "Too many variants for enum");
503
504    let names = &variants.iter().map(|(ident, _)| ident).collect::<Vec<_>>();
505
506    // Generic type parameters for the containers for the struct fields.
507    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            /// Derived columnar container for an enum.
515            #[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                    /// Container for #names.
520                    pub #names : #container_types,
521                )*
522                /// Container for variant.
523                pub variant: CVar,
524                /// Container for offset.
525                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            /// Reference for an enum.
548            #[derive(Copy, Clone, Debug)]
549            #attr
550            #vis enum #r_ident #ty_gen {
551                #(
552                    /// Enum variant for #names.
553                    #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    // Implementation of `Push<#r_ident>`
668    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        // These numbers must match those in the `Push` implementations.
707        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        // These numbers must match those in the `Push` implementations.
730        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        // For each variant of `other`, the matching and non-matching variant cases.
837        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        // For each variant of `other`, the matching and non-matching variant cases.
864        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/// A derivation for an enum type with no fields in any of its variants.
937#[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    // Bit silly, but to help us fit in a byte and reign in bloat.
953    assert!(names.len() <= 256, "Too many variants for enum");
954
955    quote! {
956        /// Derived columnar container for all-unit enum.
957        #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
958        #vis struct #c_ident <CVar = Vec<u8>> {
959            /// Container for variant.
960            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            // type Borrowed<'columnar> = #c_ident < <CVar as ::columnar::AsBytes>::Borrowed<'columnar> >;
1013            #[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}