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