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                #[inline]
159                fn push(&mut self, item: #name #ty_gen) {
160                    #destructure_self
161                    #(#push)*
162                }
163            }
164        }
165    };
166
167    let push_ref = { 
168        let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
169        let push = names.iter().map(|name| { quote! { self.#name.push(#name); } });
170        
171        let struct_generics = generics.params.iter();
172        let impl_gen = quote! { < 'columnar, #(#struct_generics,)* #(#container_types),* > };
173
174        let where_clause2 = quote! { where #(#container_types: ::columnar::Push<&'columnar #types>),* };
175
176        let destructure_self = 
177        if named { quote! { let #name { #(#names),* } = item; } }
178        else     { quote! { let #name ( #(#names),* ) = item; } };
179
180        quote! {
181            impl #impl_gen ::columnar::Push<&'columnar #name #ty_gen> for #c_ident < #(#container_types),* >  #where_clause2 {
182                #[inline]
183                fn push(&mut self, item: &'columnar #name #ty_gen) {
184                    #destructure_self
185                    #(#push)*
186                }
187            }
188        }
189    };
190
191    // Implementation of `Push<#r_ident>`
192    let push_new = { 
193
194        let reference_types = &names.iter().enumerate().map(|(index, name)| {
195            let new_name = format!("R{}", index);
196            syn::Ident::new(&new_name, name.span())
197        }).collect::<Vec<_>>();
198
199        let push = names.iter().map(|name| { quote! { self.#name.push(#name); } });
200        
201        let impl_gen = quote! { < #(#container_types,)* #(#reference_types),* > };
202
203        let where_clause = quote! { where #(#container_types: ::columnar::Push<#reference_types>),* };
204
205        let index_type = quote! { #r_ident < #(#reference_types,)* > };
206        let destructure_self = quote! { let #r_ident { #(#names),* } = item; };
207
208        quote! {
209            impl #impl_gen ::columnar::Push<#index_type> for #c_ident < #(#container_types),* > #where_clause {
210                #[inline]
211                fn push(&mut self, item: #index_type) {
212                    #destructure_self
213                    #(#push)*
214                }
215            }
216        }
217    };
218
219    let index_own = {
220        let impl_gen = quote! { < #(#container_types),* > };
221        let ty_gen = quote! { < #(#container_types),* > };
222        let where_clause = quote! { where #(#container_types: ::columnar::Index),* };
223
224        let index_type = quote! { #r_ident < #(<#container_types as ::columnar::Index>::Ref,)* > };
225
226        quote! {
227            impl #impl_gen ::columnar::Index for #c_ident #ty_gen #where_clause {
228                type Ref = #index_type;
229                fn get(&self, index: usize) -> Self::Ref {
230                    #r_ident { #(#names: self.#names.get(index),)* }
231                }
232            }
233        }
234    };
235
236    let index_ref = {
237        let impl_gen = quote! { < 'columnar, #(#container_types),* > };
238        let ty_gen = quote! { < #(#container_types),* > };
239        let where_clause = quote! { where #(&'columnar #container_types: ::columnar::Index),* };
240
241        let index_type = quote! { #r_ident < #(<&'columnar #container_types as ::columnar::Index>::Ref,)* > };
242
243        quote! {
244            impl #impl_gen ::columnar::Index for &'columnar #c_ident #ty_gen #where_clause {
245                type Ref = #index_type;
246                fn get(&self, index: usize) -> Self::Ref {
247                    #r_ident { #(#names: (&self.#names).get(index),)* }
248                }
249            }
250        }
251    };
252
253    let clear = { 
254
255        let impl_gen = quote! { < #(#container_types),* > };
256        let ty_gen = quote! { < #(#container_types),* > };
257        let where_clause = quote! { where #(#container_types: ::columnar::Clear),* };
258
259        quote! {
260            impl #impl_gen ::columnar::Clear for #c_ident #ty_gen #where_clause {
261                fn clear(&mut self) { #(self.#names.clear());* }
262            }
263        }
264    };
265
266    let length = { 
267
268        let impl_gen = quote! { < #(#container_types),* > };
269        let ty_gen = quote! { < #(#container_types),* > };
270        let where_clause = quote! { where #(#container_types: ::columnar::Len),* };
271
272        let first_name = &names[0];
273        
274        quote! {
275            impl #impl_gen ::columnar::Len for #c_ident #ty_gen #where_clause {
276                fn len(&self) -> usize {
277                    self.#first_name.len()
278                }
279            }
280        }
281    };
282
283    let as_bytes = { 
284
285        let impl_gen = quote! { <'a, #(#container_types),* > };
286        let ty_gen = quote! { < #(#container_types),* > };
287        let where_clause = quote! { where #(#container_types: ::columnar::AsBytes<'a>),* };
288        
289        quote! {
290            impl #impl_gen ::columnar::AsBytes<'a> for #c_ident #ty_gen #where_clause {
291                // type Borrowed<'columnar> = #c_ident < #(<#container_types as ::columnar::AsBytes>::Borrowed<'columnar>,)*>;
292                #[inline(always)]
293                fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
294                    let iter = None.into_iter();
295                    #( let iter = columnar::chain(iter, self.#names.as_bytes()); )*
296                    iter
297                }
298            }
299        }
300    };
301
302    let from_bytes = { 
303
304        let impl_gen = quote! { < 'columnar, #(#container_types),* > };
305        let ty_gen = quote! { < #(#container_types),* > };
306        let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>),* };
307        
308        quote! {
309            impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
310                fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
311                    #(let #names = ::columnar::FromBytes::from_bytes(bytes);)*
312                    Self { #(#names,)* }
313                }
314            }
315        }
316    };
317
318    let columnar_impl = {
319
320        let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
321
322        let where_clause2 = if let Some(struct_where) = where_clause {
323            let params = struct_where.predicates.iter(); 
324            quote! {  where #(#types : ::columnar::Columnar,)* #(#params),* }
325        }
326        else {
327            quote! { where #(#types : ::columnar::Columnar,)* }
328        };
329    
330        // Either use curly braces or parentheses to destructure the item.
331        let destructure_self = 
332        if named { quote! { let #name { #(#names),* } = self; } }
333        else     { quote! { let #name ( #(#names),* ) = self; } };
334        
335        // Either use curly braces or parentheses to destructure the item.
336        let into_self =
337        if named { quote! { #name { #(#names: ::columnar::Columnar::into_owned(other.#names)),* } } }
338        else     { quote! { #name ( #(::columnar::Columnar::into_owned(other.#names)),* ) } };
339
340        quote! {
341            impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
342                type Ref<'a> = #r_ident < #(<#types as ::columnar::Columnar>::Ref<'a>,)* > where #(#types: 'a,)*;
343                fn copy_from<'a>(&mut self, other: Self::Ref<'a>) {
344                    #destructure_self
345                    #( ::columnar::Columnar::copy_from(#names, other.#names); )*
346                }
347                fn into_owned<'a>(other: Self::Ref<'a>) -> Self {
348                    #into_self
349                }
350                type Container = #c_ident < #(<#types as ::columnar::Columnar>::Container ),* >;
351            }
352
353            impl #impl_gen ::columnar::Container<#name #ty_gen> for #c_ident < #(<#types as ::columnar::Columnar>::Container ),* > #where_clause2 {
354                type Borrowed<'a> = #c_ident < #(<<#types as ::columnar::Columnar>::Container as ::columnar::Container<#types>>::Borrowed<'a> ),* > where #(#types: 'a,)*;
355                fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
356                    #c_ident {
357                        #( #names: <<#types as ::columnar::Columnar>::Container as ::columnar::Container<#types>>::borrow(&self.#names), )*
358                    }
359                }
360            }
361        }
362    };
363
364
365    quote! {
366
367        #container_struct
368        #reference_struct
369
370        #partial_eq
371
372        #push_own
373        #push_ref
374        #push_new
375
376        #index_own
377        #index_ref
378        #length
379        #clear
380
381        #as_bytes
382        #from_bytes
383
384        #columnar_impl
385
386    }.into()
387}
388
389// TODO: Do we need to use the generics?
390fn derive_unit_struct(name: &syn::Ident, _generics: &syn::Generics, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
391    
392    let c_name = format!("{}Container", name);
393    let c_ident = syn::Ident::new(&c_name, name.span());
394
395    if attr.is_some() {
396        panic!("Unit structs do not support attributes");
397    }
398
399    quote! {
400
401        /// Derived columnar container for a unit struct.
402        #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
403        #vis struct #c_ident<CW = u64> {
404            /// Count of the number of contained records.
405            pub count: CW,
406        }
407
408        impl ::columnar::Push<#name> for #c_ident {
409            #[inline]
410            fn push(&mut self, _item: #name) {
411                self.count += 1;
412            }
413        }
414
415        impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
416            #[inline]
417            fn push(&mut self, _item: &'columnar #name) {
418                self.count += 1;
419            }
420        }
421
422        impl<CW> ::columnar::Index for #c_ident<CW> {
423            type Ref = #name;
424            fn get(&self, index: usize) -> Self::Ref {
425                #name
426            }
427        }
428
429        impl<'columnar, CW> ::columnar::Index for &'columnar #c_ident<CW> {
430            type Ref = #name;
431            fn get(&self, index: usize) -> Self::Ref {
432                #name
433            }
434        }
435
436        impl ::columnar::Clear for #c_ident {
437            fn clear(&mut self) {
438                self.count = 0;
439            }
440        }
441
442        impl<CW: Copy+::columnar::common::index::CopyAs<u64>> ::columnar::Len for #c_ident<CW> {
443            fn len(&self) -> usize {
444                use columnar::common::index::CopyAs;
445                self.count.copy_as() as usize
446            }
447        }
448
449        impl<'a> ::columnar::AsBytes<'a> for #c_ident <&'a u64> {
450            // type Borrowed<'columnar> = #c_ident;
451            #[inline(always)]
452            fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
453                std::iter::once((8, bytemuck::cast_slice(std::slice::from_ref(self.count))))
454            }
455        }
456
457        impl<'columnar> ::columnar::FromBytes<'columnar> for #c_ident <&'columnar u64> {
458            fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
459                Self { count: &bytemuck::try_cast_slice(bytes.next().unwrap()).unwrap()[0] }
460            }
461        }
462
463        impl ::columnar::Columnar for #name {
464            type Ref<'a> = #name;
465            fn copy_from<'a>(&mut self, other: Self::Ref<'a>) { *self = other; }
466            fn into_owned<'a>(other: Self::Ref<'a>) -> Self { other }
467            type Container = #c_ident;
468        }
469
470        impl ::columnar::Container<#name> for #c_ident {
471            type Borrowed<'a> = #c_ident < &'a u64 >;
472            fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
473                #c_ident { count: &self.count }
474            }
475        }
476
477    }.into()
478}
479
480/// 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.
481/// Its index `Ref` type will be an enum with parallel variants, each containing the index `Ref` types of the corresponding variant containers.
482#[allow(unused)]
483fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
484
485    if data_enum.variants.iter().all(|variant| variant.fields.is_empty()) {
486        return derive_tags(name, generics, data_enum, vis);
487    }
488
489    let c_name = format!("{}Container", name);
490    let c_ident = syn::Ident::new(&c_name, name.span());
491
492    let r_name = format!("{}Reference", name);
493    let r_ident = syn::Ident::new(&r_name, name.span());
494
495    // Record everything we know about the variants.
496    // TODO: Distinguish between unit and 0-tuple variants.
497    let variants: Vec<(&syn::Ident, Vec<_>)> = 
498    data_enum
499        .variants
500        .iter()
501        .map(|variant| (
502            &variant.ident, 
503            variant.fields.iter().map(|field| &field.ty).collect()
504        ))
505        .collect();
506
507    // Bit silly, but to help us fit in a byte and reign in bloat.
508    assert!(variants.len() <= 256, "Too many variants for enum");
509
510    let names = &variants.iter().map(|(ident, _)| ident).collect::<Vec<_>>();
511
512    // Generic type parameters for the containers for the struct fields.
513    let container_types = &names.iter().enumerate().map(|(index, name)| {
514        let new_name = format!("C{}", index);
515        syn::Ident::new(&new_name, name.span())
516    }).collect::<Vec<_>>();
517    
518    let container_struct = {
519        quote! {
520            /// Derived columnar container for an enum.
521            #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
522            #[allow(non_snake_case)]
523            #vis struct #c_ident < #(#container_types,)* CVar = Vec<u8>, COff = Vec<u64>, >{
524                #(
525                    /// Container for #names.
526                    pub #names : #container_types,
527                )*
528                /// Container for variant.
529                pub variant: CVar,
530                /// Container for offset.
531                pub offset: COff,
532            }
533        }
534    };
535
536    let reference_struct = {
537
538        let reference_types = &names.iter().enumerate().map(|(index, name)| {
539            let new_name = format!("R{}", index);
540            syn::Ident::new(&new_name, name.span())
541        }).collect::<Vec<_>>();
542    
543        let ty_gen = quote! { < #(#reference_types),* > };
544
545        let attr = if let Some(attr) = attr {
546            quote! { #[#attr] }
547        } else {
548            quote! {}
549        };
550
551
552        quote! {
553            /// Reference for an enum.
554            #[derive(Copy, Clone, Debug)]
555            #attr
556            #vis enum #r_ident #ty_gen {
557                #(
558                    /// Enum variant for #names.
559                    #names(#reference_types),
560                )*
561            }
562        }
563    };
564
565    let push_own = { 
566
567        let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
568        
569        let push = variants.iter().enumerate().map(|(index, (variant, types))| {
570
571            match data_enum.variants[index].fields {
572                syn::Fields::Unit => {
573                    quote! {
574                        #name::#variant => {
575                            self.offset.push(self.#variant.len() as u64);
576                            self.#variant.push(());
577                            self.variant.push(#index as u8);
578                        }
579                    }
580                }
581                syn::Fields::Unnamed(_) => {
582                    let temp_names = &types.iter().enumerate().map(|(index, _)| {
583                        let new_name = format!("t{}", index);
584                        syn::Ident::new(&new_name, variant.span())
585                    }).collect::<Vec<_>>();
586
587                    quote! {
588                        #name::#variant( #(#temp_names),* ) => {
589                            self.offset.push(self.#variant.len() as u64);
590                            self.#variant.push((#(#temp_names),*));
591                            self.variant.push(#index as u8);
592                        },
593                    }
594                }
595                syn::Fields::Named(_) => {
596                    unimplemented!("Named fields in enum variants are not supported by Columnar");
597                }
598            }
599        });
600
601        let struct_generics = generics.params.iter();
602        let impl_gen = quote! { < #(#struct_generics,)* #(#container_types),* > };
603
604        let push_types = variants.iter().map(|(_, types)| quote! { (#(#types),*) });
605
606        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
607
608        quote! {
609            impl #impl_gen ::columnar::Push<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
610                #[inline]
611                fn push(&mut self, item: #name #ty_gen) {
612                    match item {
613                        #( #push )*
614                    }
615                }
616            }
617        }
618    };
619
620    let push_ref = { 
621
622        let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
623
624        let push = variants.iter().enumerate().map(|(index, (variant, types))| {
625
626            match data_enum.variants[index].fields {
627                syn::Fields::Unit => {
628                    quote! {
629                        #name::#variant => {
630                            self.offset.push(self.#variant.len() as u64);
631                            self.#variant.push(());
632                            self.variant.push(#index as u8);
633                        }
634                    }
635                }
636                syn::Fields::Unnamed(_) => {
637                    let temp_names = &types.iter().enumerate().map(|(index, _)| {
638                        let new_name = format!("t{}", index);
639                        syn::Ident::new(&new_name, variant.span())
640                    }).collect::<Vec<_>>();
641
642                    quote! {
643                        #name::#variant( #(#temp_names),* ) => {
644                            self.offset.push(self.#variant.len() as u64);
645                            self.#variant.push((#(#temp_names),*));
646                            self.variant.push(#index as u8);
647                        },
648                    }
649                }
650                syn::Fields::Named(_) => {
651                    unimplemented!("Named fields in enum variants are not supported by Columnar");
652                }
653            }
654        });
655
656        let struct_generics = generics.params.iter();
657        let impl_gen = quote! { < 'columnar, #(#struct_generics,)* #(#container_types),* > };
658
659        let push_types = variants.iter().map(|(_, types)| quote! { (#(&'columnar #types),*) });
660
661        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
662
663        quote! {
664            impl #impl_gen ::columnar::Push<&'columnar #name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
665                #[inline]
666                fn push(&mut self, item: &'columnar #name #ty_gen) {
667                    match item {
668                        #( #push )*
669                    }
670                }
671            }
672        }
673    };
674
675    // Implementation of `Push<#r_ident>`
676    let push_new = { 
677
678        let reference_types = &names.iter().enumerate().map(|(index, name)| {
679            let new_name = format!("R{}", index);
680            syn::Ident::new(&new_name, name.span())
681        }).collect::<Vec<_>>();
682
683        let impl_gen = quote! { < #(#container_types,)* #(#reference_types),* > };
684
685        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#reference_types>),* };
686
687        let index_type = quote! { #r_ident < #(#reference_types,)* > };
688        let numbers = (0 .. variants.len());
689
690        quote! {
691            impl #impl_gen ::columnar::Push<#index_type> for #c_ident < #(#container_types),* > #where_clause {
692                #[inline]
693                fn push(&mut self, item: #index_type) {
694                    match item {
695                        #( 
696                            #r_ident::#names(x) => {
697                                self.offset.push(self.#names.len() as u64);
698                                self.#names.push(x);
699                                self.variant.push(#numbers as u8);
700                            }, 
701                        )*
702                    }
703                }
704            }
705        }
706    };
707    
708    let index_own = {
709        let impl_gen = quote! { < #(#container_types,)* CVal, COff> };
710        let ty_gen = quote! { < #(#container_types,)* CVal, COff> };
711        let where_clause = quote! { where #(#container_types: ::columnar::Index,)* CVal: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64>  };
712
713        let index_type = quote! { #r_ident < #(<#container_types as ::columnar::Index>::Ref,)* > };
714
715        // These numbers must match those in the `Push` implementations.
716        let numbers = (0 .. variants.len());
717
718        quote! {
719            impl #impl_gen ::columnar::Index for #c_ident #ty_gen #where_clause {
720                type Ref = #index_type;
721                fn get(&self, index: usize) -> Self::Ref {
722                    match self.variant.index_as(index) as usize {
723                        #( #numbers => #r_ident::#names(self.#names.get(self.offset.index_as(index) as usize)), )*
724                        x => panic!("Unacceptable discriminant found: {:?}", x),
725                    }
726                }
727            }
728        }
729    };
730
731    let index_ref = {
732        let impl_gen = quote! { < 'columnar, #(#container_types,)* CVal, COff> };
733        let ty_gen = quote! { < #(#container_types,)* CVal, COff> };
734        let where_clause = quote! { where #(&'columnar #container_types: ::columnar::Index,)* CVal: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64>  };
735
736        let index_type = quote! { #r_ident < #(<&'columnar #container_types as ::columnar::Index>::Ref,)* > };
737
738        // These numbers must match those in the `Push` implementations.
739        let numbers = (0 .. variants.len());
740
741        quote! {
742            impl #impl_gen ::columnar::Index for &'columnar #c_ident #ty_gen #where_clause {
743                type Ref = #index_type;
744                fn get(&self, index: usize) -> Self::Ref {
745                    match self.variant.index_as(index) as usize {
746                        #( #numbers => #r_ident::#names((&self.#names).get(self.offset.index_as(index) as usize)), )*
747                        x => panic!("Unacceptable discriminant found: {:?}", x),
748                    }
749                }
750            }
751        }
752    };
753
754    let clear = { 
755
756        let impl_gen = quote! { < #(#container_types),* > };
757        let ty_gen = quote! { < #(#container_types),* > };
758        let where_clause = quote! { where #(#container_types: ::columnar::Clear),* };
759
760        quote! {
761            impl #impl_gen ::columnar::Clear for #c_ident #ty_gen #where_clause {
762                fn clear(&mut self) { 
763                    #(self.#names.clear();)* 
764                    self.variant.clear();
765                    self.offset.clear();
766                }
767            }
768        }
769    };
770
771    let length = { 
772
773        let impl_gen = quote! { < #(#container_types,)* CVar, COff> };
774        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
775
776        quote! {
777            impl #impl_gen ::columnar::Len for #c_ident #ty_gen where CVar: ::columnar::Len {
778                fn len(&self) -> usize {
779                    self.variant.len()
780                }
781            }
782        }
783    };
784
785    let as_bytes = { 
786
787        let impl_gen = quote! { < 'a, #(#container_types,)* CVar, COff> };
788        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
789        let where_clause = quote! { where #(#container_types: ::columnar::AsBytes<'a>,)* CVar: ::columnar::AsBytes<'a>, COff: ::columnar::AsBytes<'a> };
790        
791        quote! {
792            impl #impl_gen ::columnar::AsBytes<'a> for #c_ident #ty_gen #where_clause {
793                #[inline(always)]
794                fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
795                    let iter = None.into_iter();
796                    #( let iter = columnar::chain(iter,self.#names.as_bytes()); )*
797                    let iter = columnar::chain(iter, self.variant.as_bytes());
798                    let iter = columnar::chain(iter, self.offset.as_bytes());
799                    iter
800                }
801            }
802        }
803    };
804
805    let from_bytes = { 
806
807        let impl_gen = quote! { < 'columnar, #(#container_types,)* CVar, COff> };
808        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
809        let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>,)* CVar: ::columnar::FromBytes<'columnar>, COff: ::columnar::FromBytes<'columnar> };
810        
811        quote! {
812            #[allow(non_snake_case)]
813            impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
814                fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
815                    #(let #names = ::columnar::FromBytes::from_bytes(bytes);)*
816                    let variant = ::columnar::FromBytes::from_bytes(bytes);
817                    let offset = ::columnar::FromBytes::from_bytes(bytes);
818                    Self { #(#names,)* variant, offset }
819                }
820            }
821        }
822    };
823
824    let columnar_impl = {
825
826        let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
827
828        let types = &variants.iter().flat_map(|(_, types)| types).collect::<Vec<_>>();
829
830        let where_clause2 = if let Some(enum_where) = where_clause {
831            let params = enum_where.predicates.iter(); 
832            quote! {  where #(#types : ::columnar::Columnar,)* #(#params),* }
833        }
834        else {
835            quote! { where #(#types : ::columnar::Columnar,)* }
836        };
837
838
839        let variant_types = &variants.iter().map(|(_, types)| quote! { (#(#types),*) }).collect::<Vec<_>>();
840
841        let container_types = &variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Container }).collect::<Vec<_>>();
842
843        let reference_args = variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Ref<'a> });
844
845        // For each variant of `other`, the matching and non-matching variant cases.
846        let copy_from = variants.iter().enumerate().map(|(index, (variant, types))| {
847
848            if data_enum.variants[index].fields == syn::Fields::Unit {
849                quote! { 
850                    (#name::#variant, #r_ident::#variant(_)) => { }
851                    (_, #r_ident::#variant(_)) => { *self = #name::#variant; }
852                }
853            }
854            else {
855                let temp_names1 = &types.iter().enumerate().map(|(index, _)| {
856                    let new_name = format!("s{}", index);
857                    syn::Ident::new(&new_name, variant.span())
858                }).collect::<Vec<_>>();
859                let temp_names2 = &types.iter().enumerate().map(|(index, _)| {
860                    let new_name = format!("t{}", index);
861                    syn::Ident::new(&new_name, variant.span())
862                }).collect::<Vec<_>>();
863
864                quote! {
865                    (#name::#variant( #( #temp_names1 ),* ), #r_ident::#variant( ( #( #temp_names2 ),* ) )) => {
866                        #( ::columnar::Columnar::copy_from(#temp_names1, #temp_names2); )*
867                    }
868                }
869            }
870        }).collect::<Vec<_>>();
871
872        // For each variant of `other`, the matching and non-matching variant cases.
873        let into_owned = variants.iter().enumerate().map(|(index, (variant, types))| {
874
875            if data_enum.variants[index].fields == syn::Fields::Unit {
876                quote! { #r_ident::#variant(_) => #name::#variant, }
877            }
878            else {
879                let temp_names = &types.iter().enumerate().map(|(index, _)| {
880                    let new_name = format!("t{}", index);
881                    syn::Ident::new(&new_name, variant.span())
882                }).collect::<Vec<_>>();
883
884                quote! {
885                    #r_ident::#variant(( #( #temp_names ),* )) => {
886                        #name::#variant( #( ::columnar::Columnar::into_owned(#temp_names) ),* )
887                    },
888                }
889            }
890        }).collect::<Vec<_>>();
891
892
893        quote! {
894            impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
895                type Ref<'a> = #r_ident < #(#reference_args,)* > where Self: 'a, #(#variant_types: 'a,)*;
896                fn copy_from<'a>(&mut self, other: Self::Ref<'a>) {
897                    match (&mut *self, other) {
898                        #( #copy_from )*
899                        (_, other) => { *self = Self::into_owned(other); }
900                    }
901                }
902                fn into_owned<'a>(other: Self::Ref<'a>) -> Self {
903                    match other {
904                        #( #into_owned )*
905                    }
906                }
907                type Container = #c_ident < #(#container_types),* >;
908            }
909
910            impl #impl_gen ::columnar::Container<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause2 {
911                type Borrowed<'a> = #c_ident < #( < #container_types as ::columnar::Container<#variant_types> >::Borrowed<'a>, )* &'a [u8], &'a [u64] > where #(#variant_types: 'a,)*;
912                fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
913                    #c_ident {
914                        #(#names: self.#names.borrow(),)*
915                        variant: self.variant.borrow(),
916                        offset: self.offset.borrow(),
917                    }
918                }
919            }
920        }
921    };
922
923    quote! {
924
925        #container_struct
926        #reference_struct
927
928        #push_own
929        #push_ref
930        #push_new
931
932        #index_own
933        #index_ref
934        #length
935        #clear
936
937        #as_bytes
938        #from_bytes
939
940        #columnar_impl
941
942    }.into()
943}
944
945/// A derivation for an enum type with no fields in any of its variants.
946#[allow(unused)]
947fn derive_tags(name: &syn::Ident, _generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility) -> proc_macro::TokenStream {
948
949    let c_name = format!("{}Container", name);
950    let c_ident = syn::Ident::new(&c_name, name.span());
951
952    let names: Vec<&syn::Ident> =
953    data_enum
954        .variants
955        .iter()
956        .map(|variant| &variant.ident)
957        .collect();
958
959    let indices: &Vec<u8> = &(0 .. names.len()).map(|x| x as u8).collect();
960
961    // Bit silly, but to help us fit in a byte and reign in bloat.
962    assert!(names.len() <= 256, "Too many variants for enum");
963
964    quote! {
965        /// Derived columnar container for all-unit enum.
966        #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
967        #vis struct #c_ident <CVar = Vec<u8>> {
968            /// Container for variant.
969            pub variant: CVar,
970        }
971
972        impl ::columnar::Push<#name> for #c_ident {
973            #[inline]
974            fn push(&mut self, item: #name) {
975                match item {
976                    #( #name::#names => self.variant.push(#indices), )*
977                }
978            }
979        }
980
981        impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
982            #[inline]
983            fn push(&mut self, item: &'columnar #name) {
984                match *item {
985                    #( #name::#names => self.variant.push(#indices), )*
986                }
987            }
988        }
989
990        impl<CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for #c_ident <CVar> {
991            type Ref = #name;
992            fn get(&self, index: usize) -> Self::Ref {
993                match self.variant.index_as(index) {
994                    #( #indices => #name::#names, )*
995                    x => panic!("Unacceptable discriminant found: {:?}", x),
996                }
997            }
998        }
999
1000        impl<'columnar, CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for &'columnar #c_ident <CVar> {
1001            type Ref = #name;
1002            fn get(&self, index: usize) -> Self::Ref {
1003                match self.variant.index_as(index) {
1004                    #( #indices => #name::#names, )*
1005                    x => panic!("Unacceptable discriminant found: {:?}", x),
1006                }
1007            }
1008        }
1009
1010        impl<CVar: ::columnar::Clear> ::columnar::Clear for #c_ident <CVar> {
1011            fn clear(&mut self) {
1012                self.variant.clear();
1013            }
1014        }
1015
1016        impl<CVar: ::columnar::Len> ::columnar::Len for #c_ident <CVar> {
1017            fn len(&self) -> usize {
1018                self.variant.len()
1019            }
1020        }
1021
1022        impl<'a, CVar: ::columnar::AsBytes<'a>> ::columnar::AsBytes<'a> for #c_ident <CVar> {
1023            // type Borrowed<'columnar> = #c_ident < <CVar as ::columnar::AsBytes>::Borrowed<'columnar> >;
1024            #[inline(always)]
1025            fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
1026                self.variant.as_bytes()
1027            }
1028        }
1029
1030        impl<'columnar, CVar: ::columnar::FromBytes<'columnar>> ::columnar::FromBytes<'columnar> for #c_ident <CVar> {
1031            fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
1032                Self { variant: ::columnar::FromBytes::from_bytes(bytes) }
1033            }
1034        }
1035
1036        impl ::columnar::Columnar for #name {
1037            type Ref<'a> = #name;
1038            fn copy_from<'a>(&mut self, other: Self::Ref<'a>) { *self = other; }
1039            fn into_owned<'a>(other: Self::Ref<'a>) -> Self { other }
1040            type Container = #c_ident;
1041        }
1042
1043        impl<CV: ::columnar::Container<u8>> ::columnar::Container<#name> for #c_ident <CV> {
1044            type Borrowed<'a> = #c_ident < CV::Borrowed<'a> > where CV: 'a;
1045            fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
1046                #c_ident {
1047                    variant: self.variant.borrow()
1048                }
1049            }
1050        }
1051    }.into()
1052}