Skip to main content

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                const SLICE_COUNT: usize = 0 #(+ <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT)*;
302                #[inline]
303                fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
304                    debug_assert!(index < Self::SLICE_COUNT);
305                    let mut _offset = 0;
306                    #(
307                        if index < _offset + <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT {
308                            return self.#names.get_byte_slice(index - _offset);
309                        }
310                        _offset += <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT;
311                    )*
312                    panic!("get_byte_slice: index out of bounds")
313                }
314            }
315        }
316    };
317
318    let from_bytes = {
319
320        let impl_gen = quote! { < 'columnar, #(#container_types),* > };
321        let ty_gen = quote! { < #(#container_types),* > };
322        let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>),* };
323
324        quote! {
325            impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
326                const SLICE_COUNT: usize = 0 #(+ <#container_types>::SLICE_COUNT)*;
327                #[inline(always)]
328                fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
329                    Self { #(#names: ::columnar::FromBytes::from_bytes(bytes),)* }
330                }
331                #[inline(always)]
332                fn from_store(store: &::columnar::bytes::indexed::DecodedStore<'columnar>, offset: &mut usize) -> Self {
333                    Self { #(#names: ::columnar::FromBytes::from_store(store, offset),)* }
334                }
335                fn element_sizes(sizes: &mut Vec<usize>) -> ::core::result::Result<(), String> {
336                    #(<#container_types>::element_sizes(sizes)?;)*
337                    Ok(())
338                }
339            }
340        }
341    };
342
343    let columnar_impl = {
344
345        let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
346
347        let where_clause2 = if let Some(struct_where) = where_clause {
348            let params = struct_where.predicates.iter();
349            quote! {  where #(#types : ::columnar::Columnar,)* #(#params),* }
350        }
351        else {
352            quote! { where #(#types : ::columnar::Columnar,)* }
353        };
354
355        // Either use curly braces or parentheses to destructure the item.
356        let destructure_self =
357        if named { quote! { let #name { #(#names),* } = self; } }
358        else     { quote! { let #name ( #(#names),* ) = self; } };
359
360        // Either use curly braces or parentheses to destructure the item.
361        let into_self =
362        if named { quote! { #name { #(#names: ::columnar::Columnar::into_owned(other.#names)),* } } }
363        else     { quote! { #name ( #(::columnar::Columnar::into_owned(other.#names)),* ) } };
364
365        quote! {
366            impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
367                #[inline(always)]
368                fn copy_from<'a>(&mut self, other: ::columnar::Ref<'a, Self>) {
369                    #destructure_self
370                    #( ::columnar::Columnar::copy_from(#names, other.#names); )*
371                }
372                #[inline(always)]
373                fn into_owned<'a>(other: ::columnar::Ref<'a, Self>) -> Self {
374                    #into_self
375                }
376                type Container = #c_ident < #(<#types as ::columnar::Columnar>::Container ),* >;
377            }
378
379            impl < #( #container_types: ::columnar::Borrow ),* > ::columnar::Borrow for #c_ident < #( #container_types ),* > {
380                type Ref<'a> = #r_ident < #(<#container_types as ::columnar::Borrow>::Ref<'a>,)* > where #(#container_types: 'a,)*;
381                type Borrowed<'a> = #c_ident < #(<#container_types as ::columnar::Borrow>::Borrowed<'a> ),* > where #(#container_types: 'a,)*;
382                #[inline(always)]
383                fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
384                    #c_ident {
385                        #( #names: <#container_types as ::columnar::Borrow>::borrow(&self.#names), )*
386                    }
387                }
388                #[inline(always)]
389                fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> {
390                    #c_ident {
391                        #( #names: <#container_types as ::columnar::Borrow>::reborrow(thing.#names), )*
392                    }
393                }
394                #[inline(always)]
395                fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> {
396                    #r_ident {
397                        #( #names: <#container_types as ::columnar::Borrow>::reborrow_ref(thing.#names), )*
398                    }
399                }
400            }
401
402            impl < #( #container_types: ::columnar::Container ),* > ::columnar::Container for #c_ident < #( #container_types ),* > {
403                #[inline(always)]
404                fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: std::ops::Range<usize>) {
405                    #( self.#names.extend_from_self(other.#names, range.clone()); )*
406                }
407
408                fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone {
409                    #( self.#names.reserve_for(selves.clone().map(|x| x.#names)); )*
410                }
411            }
412        }
413    };
414
415
416    quote! {
417
418        #container_struct
419        #reference_struct
420
421        #partial_eq
422
423        #push_own
424        #push_ref
425        #push_new
426
427        #index_own
428        #index_ref
429        #length
430        #clear
431
432        #as_bytes
433        #from_bytes
434
435        #columnar_impl
436
437    }.into()
438}
439
440// TODO: Do we need to use the generics?
441fn derive_unit_struct(name: &syn::Ident, _generics: &syn::Generics, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
442
443    let c_name = format!("{}Container", name);
444    let c_ident = syn::Ident::new(&c_name, name.span());
445
446    if attr.is_some() {
447        panic!("Unit structs do not support attributes");
448    }
449
450    #[cfg(feature = "serde")]
451    let derive = quote! { #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)] };
452    #[cfg(not(feature = "serde"))]
453    let derive = quote! { #[derive(Copy, Clone, Debug, Default)] };
454
455    quote! {
456
457        /// Derived columnar container for a unit struct.
458        #derive
459        #vis struct #c_ident<CW = u64> {
460            /// Count of the number of contained records.
461            pub count: CW,
462        }
463
464        impl ::columnar::Push<#name> for #c_ident {
465            #[inline]
466            fn push(&mut self, _item: #name) {
467                self.count += 1;
468            }
469        }
470
471        impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
472            #[inline]
473            fn push(&mut self, _item: &'columnar #name) {
474                self.count += 1;
475            }
476        }
477
478        impl<CW> ::columnar::Index for #c_ident<CW> {
479            type Ref = #name;
480            #[inline(always)]
481            fn get(&self, index: usize) -> Self::Ref {
482                #name
483            }
484        }
485
486        impl<'columnar, CW> ::columnar::Index for &'columnar #c_ident<CW> {
487            type Ref = #name;
488            #[inline(always)]
489            fn get(&self, index: usize) -> Self::Ref {
490                #name
491            }
492        }
493
494        impl ::columnar::Clear for #c_ident {
495            #[inline(always)]
496            fn clear(&mut self) {
497                self.count = 0;
498            }
499        }
500
501        impl<CW: Copy+::columnar::common::index::CopyAs<u64>> ::columnar::Len for #c_ident<CW> {
502            #[inline(always)]
503            fn len(&self) -> usize {
504                use ::columnar::common::index::CopyAs;
505                self.count.copy_as() as usize
506            }
507        }
508
509        impl<'a> ::columnar::AsBytes<'a> for #c_ident <&'a u64> {
510            const SLICE_COUNT: usize = 1;
511            #[inline]
512            fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
513                debug_assert!(index < Self::SLICE_COUNT);
514                (8, ::columnar::bytemuck::cast_slice(::core::slice::from_ref(self.count)))
515            }
516        }
517
518        impl<'columnar> ::columnar::FromBytes<'columnar> for #c_ident <&'columnar u64> {
519            const SLICE_COUNT: usize = 1;
520            #[inline(always)]
521            fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
522                Self { count: &::columnar::bytemuck::try_cast_slice(bytes.next().unwrap()).unwrap()[0] }
523            }
524            #[inline(always)]
525            fn from_store(store: &::columnar::bytes::indexed::DecodedStore<'columnar>, offset: &mut usize) -> Self {
526                let (w, _tail) = store.get(*offset);
527                *offset += 1;
528                Self { count: w.first().unwrap_or(&0) }
529            }
530            fn element_sizes(sizes: &mut Vec<usize>) -> ::core::result::Result<(), String> {
531                sizes.push(8);
532                Ok(())
533            }
534        }
535
536        impl ::columnar::Columnar for #name {
537            #[inline(always)]
538            fn copy_from<'a>(&mut self, other: ::columnar::Ref<'a, Self>) { *self = other; }
539            #[inline(always)]
540            fn into_owned<'a>(other: ::columnar::Ref<'a, Self>) -> Self { other }
541            type Container = #c_ident;
542        }
543
544        impl ::columnar::Borrow for #c_ident {
545            type Ref<'a> = #name;
546            type Borrowed<'a> = #c_ident < &'a u64 >;
547            #[inline(always)]
548            fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
549                #c_ident { count: &self.count }
550            }
551            #[inline(always)]
552            fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> {
553                #c_ident { count: thing.count }
554            }
555            #[inline(always)]
556            fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> { thing }
557        }
558
559        impl ::columnar::Container for #c_ident {
560            #[inline(always)]
561            fn extend_from_self(&mut self, _other: Self::Borrowed<'_>, range: std::ops::Range<usize>) {
562                self.count += range.len() as u64;
563            }
564
565            fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone { }
566        }
567
568    }.into()
569}
570
571/// 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.
572/// Its index `Ref` type will be an enum with parallel variants, each containing the index `Ref` types of the corresponding variant containers.
573#[allow(unused)]
574fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility, attr: Option<proc_macro2::TokenStream>) -> proc_macro::TokenStream {
575
576    if data_enum.variants.iter().all(|variant| variant.fields.is_empty()) {
577        return derive_tags(name, generics, data_enum, vis);
578    }
579
580    let c_name = format!("{}Container", name);
581    let c_ident = syn::Ident::new(&c_name, name.span());
582
583    let r_name = format!("{}Reference", name);
584    let r_ident = syn::Ident::new(&r_name, name.span());
585
586    // Record everything we know about the variants.
587    let variants: Vec<(&syn::Ident, Vec<_>)> =
588    data_enum
589        .variants
590        .iter()
591        .map(|variant| (
592            &variant.ident,
593            variant.fields.iter().map(|field| &field.ty).collect()
594        ))
595        .collect();
596
597    // Bit silly, but to help us fit in a byte and reign in bloat.
598    assert!(variants.len() <= 256, "Too many variants for enum");
599
600    let names = &variants.iter().map(|(ident, _)| ident).collect::<Vec<_>>();
601
602    // Generic type parameters for the containers for the struct fields.
603    let container_types = &names.iter().enumerate().map(|(index, name)| {
604        let new_name = format!("C{}", index);
605        syn::Ident::new(&new_name, name.span())
606    }).collect::<Vec<_>>();
607
608    #[cfg(feature = "serde")]
609    let derive = quote! { #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)] };
610    #[cfg(not(feature = "serde"))]
611    let derive = quote! { #[derive(Copy, Clone, Debug, Default)] };
612
613    let container_struct = {
614        quote! {
615            /// Derived columnar container for an enum.
616            #derive
617            #[allow(non_snake_case)]
618            #vis struct #c_ident < #(#container_types,)* CVar = Vec<u8>, COff = Vec<u64>, >{
619                #(
620                    /// Container for #names.
621                    pub #names : #container_types,
622                )*
623                /// Discriminant tracking for variants.
624                pub indexes: ::columnar::Discriminant<CVar, COff>,
625            }
626        }
627    };
628
629    let reference_struct = {
630
631        let reference_types = &names.iter().enumerate().map(|(index, name)| {
632            let new_name = format!("R{}", index);
633            syn::Ident::new(&new_name, name.span())
634        }).collect::<Vec<_>>();
635
636        let ty_gen = quote! { < #(#reference_types),* > };
637
638        let attr = if let Some(attr) = attr {
639            quote! { #[#attr] }
640        } else {
641            quote! {}
642        };
643
644
645        quote! {
646            /// Reference for an enum.
647            #[derive(Copy, Clone, Debug)]
648            #attr
649            #vis enum #r_ident #ty_gen {
650                #(
651                    /// Enum variant for #names.
652                    #names(#reference_types),
653                )*
654            }
655        }
656    };
657
658    let push_own = {
659
660        let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
661
662        let push = variants.iter().enumerate().map(|(index, (variant, types))| {
663
664            match &data_enum.variants[index].fields {
665                syn::Fields::Unit => {
666                    quote! {
667                        #name::#variant => {
668                            self.indexes.push(#index as u8, self.#variant.len() as u64);
669                            self.#variant.push(());
670                        }
671                    }
672                }
673                syn::Fields::Unnamed(_) => {
674                    let temp_names = &types.iter().enumerate().map(|(index, _)| {
675                        let new_name = format!("t{}", index);
676                        syn::Ident::new(&new_name, variant.span())
677                    }).collect::<Vec<_>>();
678
679                    quote! {
680                        #name::#variant( #(#temp_names),* ) => {
681                            self.indexes.push(#index as u8, self.#variant.len() as u64);
682                            self.#variant.push((#(#temp_names),*));
683                        },
684                    }
685                }
686                syn::Fields::Named(fields) => {
687                    let field_names = &fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect::<Vec<_>>();
688
689                    quote! {
690                        #name::#variant { #(#field_names),* } => {
691                            self.indexes.push(#index as u8, self.#variant.len() as u64);
692                            self.#variant.push((#(#field_names),*));
693                        },
694                    }
695                }
696            }
697        });
698
699        let struct_generics = generics.params.iter();
700        let impl_gen = quote! { < #(#struct_generics,)* #(#container_types),* > };
701
702        let push_types = variants.iter().map(|(_, types)| quote! { (#(#types),*) });
703
704        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
705
706        quote! {
707            impl #impl_gen ::columnar::Push<#name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
708                #[inline]
709                fn push(&mut self, item: #name #ty_gen) {
710                    match item {
711                        #( #push )*
712                    }
713                }
714            }
715        }
716    };
717
718    let push_ref = {
719
720        let (_impl_gen, ty_gen, _where_clause) = generics.split_for_impl();
721
722        let push = variants.iter().enumerate().map(|(index, (variant, types))| {
723
724            match &data_enum.variants[index].fields {
725                syn::Fields::Unit => {
726                    quote! {
727                        #name::#variant => {
728                            self.indexes.push(#index as u8, self.#variant.len() as u64);
729                            self.#variant.push(());
730                        }
731                    }
732                }
733                syn::Fields::Unnamed(_) => {
734                    let temp_names = &types.iter().enumerate().map(|(index, _)| {
735                        let new_name = format!("t{}", index);
736                        syn::Ident::new(&new_name, variant.span())
737                    }).collect::<Vec<_>>();
738
739                    quote! {
740                        #name::#variant( #(#temp_names),* ) => {
741                            self.indexes.push(#index as u8, self.#variant.len() as u64);
742                            self.#variant.push((#(#temp_names),*));
743                        },
744                    }
745                }
746                syn::Fields::Named(fields) => {
747                    let field_names = &fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect::<Vec<_>>();
748
749                    quote! {
750                        #name::#variant { #(#field_names),* } => {
751                            self.indexes.push(#index as u8, self.#variant.len() as u64);
752                            self.#variant.push((#(#field_names),*));
753                        },
754                    }
755                }
756            }
757        });
758
759        let struct_generics = generics.params.iter();
760        let impl_gen = quote! { < 'columnar, #(#struct_generics,)* #(#container_types),* > };
761
762        let push_types = variants.iter().map(|(_, types)| quote! { (#(&'columnar #types),*) });
763
764        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#push_types>),* };
765
766        quote! {
767            impl #impl_gen ::columnar::Push<&'columnar #name #ty_gen> for #c_ident < #(#container_types),* > #where_clause {
768                #[inline]
769                fn push(&mut self, item: &'columnar #name #ty_gen) {
770                    match item {
771                        #( #push )*
772                    }
773                }
774            }
775        }
776    };
777
778    // Implementation of `Push<#r_ident>`
779    let push_new = {
780
781        let reference_types = &names.iter().enumerate().map(|(index, name)| {
782            let new_name = format!("R{}", index);
783            syn::Ident::new(&new_name, name.span())
784        }).collect::<Vec<_>>();
785
786        let impl_gen = quote! { < #(#container_types,)* #(#reference_types),* > };
787
788        let where_clause = quote! { where #(#container_types: ::columnar::Len + ::columnar::Push<#reference_types>),* };
789
790        let index_type = quote! { #r_ident < #(#reference_types,)* > };
791        let numbers = (0 .. variants.len());
792
793        quote! {
794            impl #impl_gen ::columnar::Push<#index_type> for #c_ident < #(#container_types),* > #where_clause {
795                #[inline]
796                fn push(&mut self, item: #index_type) {
797                    match item {
798                        #(
799                            #r_ident::#names(x) => {
800                                self.indexes.push(#numbers as u8, self.#names.len() as u64);
801                                self.#names.push(x);
802                            },
803                        )*
804                    }
805                }
806            }
807        }
808    };
809
810    let index_own = {
811        let impl_gen = quote! { < #(#container_types,)* CVar, COff> };
812        let ty_gen = quote! { < #(#container_types,)* CVar, COff> };
813        let where_clause = quote! { where #(#container_types: ::columnar::Index,)* CVar: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64>  };
814
815        let index_type = quote! { #r_ident < #(<#container_types as ::columnar::Index>::Ref,)* > };
816
817        // These numbers must match those in the `Push` implementations.
818        let numbers = (0 .. variants.len());
819
820        quote! {
821            impl #impl_gen ::columnar::Index for #c_ident #ty_gen #where_clause {
822                type Ref = #index_type;
823                #[inline(always)]
824                fn get(&self, index: usize) -> Self::Ref {
825                    let (variant, offset) = self.indexes.get(index);
826                    match variant as usize {
827                        #( #numbers => #r_ident::#names(self.#names.get(offset as usize)), )*
828                        x => panic!("Unacceptable discriminant found: {:?}", x),
829                    }
830                }
831            }
832        }
833    };
834
835    let index_ref = {
836        let impl_gen = quote! { < 'columnar, #(#container_types,)* CVar, COff> };
837        let ty_gen = quote! { < #(#container_types,)* CVar, COff> };
838        let where_clause = quote! { where #(&'columnar #container_types: ::columnar::Index,)* CVar: ::columnar::Len + ::columnar::IndexAs<u8>, COff: ::columnar::Len + ::columnar::IndexAs<u64>  };
839
840        let index_type = quote! { #r_ident < #(<&'columnar #container_types as ::columnar::Index>::Ref,)* > };
841
842        // These numbers must match those in the `Push` implementations.
843        let numbers = (0 .. variants.len());
844
845        quote! {
846            impl #impl_gen ::columnar::Index for &'columnar #c_ident #ty_gen #where_clause {
847                type Ref = #index_type;
848                #[inline(always)]
849                fn get(&self, index: usize) -> Self::Ref {
850                    let (variant, offset) = self.indexes.get(index);
851                    match variant as usize {
852                        #( #numbers => #r_ident::#names((&self.#names).get(offset as usize)), )*
853                        x => panic!("Unacceptable discriminant found: {:?}", x),
854                    }
855                }
856            }
857        }
858    };
859
860    let clear = {
861
862        let impl_gen = quote! { < #(#container_types),* > };
863        let ty_gen = quote! { < #(#container_types),* > };
864        let where_clause = quote! { where #(#container_types: ::columnar::Clear),* };
865
866        quote! {
867            impl #impl_gen ::columnar::Clear for #c_ident #ty_gen #where_clause {
868                #[inline(always)]
869                fn clear(&mut self) {
870                    #(self.#names.clear();)*
871                    self.indexes.clear();
872                }
873            }
874        }
875    };
876
877    let length = {
878
879        let impl_gen = quote! { < #(#container_types,)* CVar, COff> };
880        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
881
882        quote! {
883            impl #impl_gen ::columnar::Len for #c_ident #ty_gen where CVar: ::columnar::Len, COff: ::columnar::Len + ::columnar::IndexAs<u64> {
884                #[inline(always)]
885                fn len(&self) -> usize {
886                    self.indexes.len()
887                }
888            }
889        }
890    };
891
892    let as_bytes = {
893
894        let impl_gen = quote! { < 'a, #(#container_types,)* CVar, COff> };
895        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
896        let where_clause = quote! { where #(#container_types: ::columnar::AsBytes<'a>,)* ::columnar::Discriminant<CVar, COff>: ::columnar::AsBytes<'a> };
897
898        quote! {
899            impl #impl_gen ::columnar::AsBytes<'a> for #c_ident #ty_gen #where_clause {
900                const SLICE_COUNT: usize = 0 #(+ <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT)* + <::columnar::Discriminant<CVar, COff> as ::columnar::AsBytes<'a>>::SLICE_COUNT;
901                #[inline]
902                fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
903                    debug_assert!(index < Self::SLICE_COUNT);
904                    let mut _offset = 0;
905                    #(
906                        if index < _offset + <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT {
907                            return self.#names.get_byte_slice(index - _offset);
908                        }
909                        _offset += <#container_types as ::columnar::AsBytes<'a>>::SLICE_COUNT;
910                    )*
911                    self.indexes.get_byte_slice(index - _offset)
912                }
913            }
914        }
915    };
916
917    let from_bytes = {
918
919        let impl_gen = quote! { < 'columnar, #(#container_types,)* CVar, COff> };
920        let ty_gen = quote! { < #(#container_types,)* CVar, COff > };
921        let where_clause = quote! { where #(#container_types: ::columnar::FromBytes<'columnar>,)* ::columnar::Discriminant<CVar, COff>: ::columnar::FromBytes<'columnar> };
922
923        quote! {
924            #[allow(non_snake_case)]
925            impl #impl_gen ::columnar::FromBytes<'columnar> for #c_ident #ty_gen #where_clause {
926                const SLICE_COUNT: usize = 0 #(+ <#container_types>::SLICE_COUNT)* + <::columnar::Discriminant<CVar, COff>>::SLICE_COUNT;
927                #[inline(always)]
928                fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
929                    Self {
930                        #(#names: ::columnar::FromBytes::from_bytes(bytes),)*
931                        indexes: ::columnar::FromBytes::from_bytes(bytes),
932                    }
933                }
934                #[inline(always)]
935                fn from_store(store: &::columnar::bytes::indexed::DecodedStore<'columnar>, offset: &mut usize) -> Self {
936                    Self {
937                        #(#names: ::columnar::FromBytes::from_store(store, offset),)*
938                        indexes: ::columnar::FromBytes::from_store(store, offset),
939                    }
940                }
941                fn element_sizes(sizes: &mut Vec<usize>) -> ::core::result::Result<(), String> {
942                    #(<#container_types>::element_sizes(sizes)?;)*
943                    <::columnar::Discriminant<CVar, COff>>::element_sizes(sizes)?;
944                    Ok(())
945                }
946            }
947        }
948    };
949
950    let columnar_impl = {
951
952        let (impl_gen, ty_gen, where_clause) = generics.split_for_impl();
953
954        let types = &variants.iter().flat_map(|(_, types)| types).collect::<Vec<_>>();
955
956        let where_clause2 = if let Some(enum_where) = where_clause {
957            let params = enum_where.predicates.iter();
958            quote! {  where #(#types : ::columnar::Columnar,)* #(#params),* }
959        }
960        else {
961            quote! { where #(#types : ::columnar::Columnar,)* }
962        };
963
964
965        let variant_types = &variants.iter().map(|(_, types)| quote! { (#(#types),*) }).collect::<Vec<_>>();
966
967        let container_types = &variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Container }).collect::<Vec<_>>();
968        // Generic type parameters for the containers for the struct fields.
969        let container_names = &names.iter().enumerate().map(|(index, name)| {
970            let new_name = format!("C{}", index);
971            syn::Ident::new(&new_name, name.span())
972        }).collect::<Vec<_>>();
973
974        let reference_args = variants.iter().map(|(_, types)| quote! { <(#(#types),*) as ::columnar::Columnar>::Ref<'a> });
975        let reference_args2 = reference_args.clone();
976
977        // For each variant of `other`, the matching and non-matching variant cases.
978        let copy_from = variants.iter().enumerate().map(|(index, (variant, types))| {
979
980            if data_enum.variants[index].fields == syn::Fields::Unit {
981                quote! {
982                    (#name::#variant, #r_ident::#variant(_)) => { }
983                    (_, #r_ident::#variant(_)) => { *self = #name::#variant; }
984                }
985            }
986            else {
987                let temp_names1 = &types.iter().enumerate().map(|(index, _)| {
988                    let new_name = format!("s{}", index);
989                    syn::Ident::new(&new_name, variant.span())
990                }).collect::<Vec<_>>();
991                let temp_names2 = &types.iter().enumerate().map(|(index, _)| {
992                    let new_name = format!("t{}", index);
993                    syn::Ident::new(&new_name, variant.span())
994                }).collect::<Vec<_>>();
995
996                let destructure = match &data_enum.variants[index].fields {
997                    syn::Fields::Named(fields) => {
998                        let field_names: Vec<_> = fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect();
999                        quote! { #name::#variant { #(#field_names: #temp_names1),* } }
1000                    }
1001                    _ => quote! { #name::#variant( #(#temp_names1),* ) }
1002                };
1003
1004                quote! {
1005                    (#destructure, #r_ident::#variant( ( #( #temp_names2 ),* ) )) => {
1006                        #( ::columnar::Columnar::copy_from(#temp_names1, #temp_names2); )*
1007                    }
1008                }
1009            }
1010        }).collect::<Vec<_>>();
1011
1012        // For each variant of `other`, the matching and non-matching variant cases.
1013        let into_owned = variants.iter().enumerate().map(|(index, (variant, types))| {
1014
1015            if data_enum.variants[index].fields == syn::Fields::Unit {
1016                quote! { #r_ident::#variant(_) => #name::#variant, }
1017            }
1018            else {
1019                let temp_names = &types.iter().enumerate().map(|(index, _)| {
1020                    let new_name = format!("t{}", index);
1021                    syn::Ident::new(&new_name, variant.span())
1022                }).collect::<Vec<_>>();
1023
1024                let reconstruct = match &data_enum.variants[index].fields {
1025                    syn::Fields::Named(fields) => {
1026                        let field_names: Vec<_> = fields.named.iter().map(|f| f.ident.as_ref().unwrap()).collect();
1027                        quote! { #name::#variant { #(#field_names: ::columnar::Columnar::into_owned(#temp_names)),* } }
1028                    }
1029                    _ => quote! { #name::#variant( #( ::columnar::Columnar::into_owned(#temp_names) ),* ) }
1030                };
1031
1032                quote! {
1033                    #r_ident::#variant(( #( #temp_names ),* )) => {
1034                        #reconstruct
1035                    },
1036                }
1037            }
1038        }).collect::<Vec<_>>();
1039
1040        // For each variant, the reborrow case.
1041        let reborrow_ref = variants.iter().enumerate().zip(container_names.iter()).map(|((index, (variant, types)), cname)| {
1042            quote! {
1043                #r_ident::#variant(( potato )) => {
1044                    #r_ident::#variant((  < (#cname) as ::columnar::Borrow >::reborrow_ref::<'b, 'a>( potato ) ))
1045                },
1046            }
1047        }).collect::<Vec<_>>();
1048
1049        // Helper identifiers for `extend_from_self` local variables.
1050        let len_idents = &names.iter().map(|n| syn::Ident::new(&format!("len_{}", n.to_string().to_lowercase()), n.span())).collect::<Vec<_>>();
1051        let count_idents = &names.iter().map(|n| syn::Ident::new(&format!("count_{}", n.to_string().to_lowercase()), n.span())).collect::<Vec<_>>();
1052        let start_idents = &names.iter().map(|n| syn::Ident::new(&format!("start_{}", n.to_string().to_lowercase()), n.span())).collect::<Vec<_>>();
1053        let variant_indices = &(0..variants.len()).map(|i| i as u8).collect::<Vec<_>>();
1054
1055        quote! {
1056            impl #impl_gen ::columnar::Columnar for #name #ty_gen #where_clause2 {
1057                #[inline(always)]
1058                fn copy_from<'a>(&mut self, other: ::columnar::Ref<'a, Self>) {
1059                    match (&mut *self, other) {
1060                        #( #copy_from )*
1061                        (_, other) => { *self = Self::into_owned(other); }
1062                    }
1063                }
1064                #[inline(always)]
1065                fn into_owned<'a>(other: ::columnar::Ref<'a, Self>) -> Self {
1066                    match other {
1067                        #( #into_owned )*
1068                    }
1069                }
1070                type Container = #c_ident < #(#container_types),* >;
1071            }
1072
1073            impl < #(#container_names : ::columnar::Borrow ),* > ::columnar::Borrow for #c_ident < #(#container_names),* > {
1074                type Ref<'a> = #r_ident < #( <#container_names as ::columnar::Borrow>::Ref<'a> ,)* > where Self: 'a, #(#container_names: 'a,)*;
1075                type Borrowed<'a> = #c_ident < #( < #container_names as ::columnar::Borrow >::Borrowed<'a>, )* &'a [u8], &'a [u64] > where #(#container_names: 'a,)*;
1076                #[inline(always)]
1077                fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
1078                    #c_ident {
1079                        #(#names: self.#names.borrow(),)*
1080                        indexes: self.indexes.borrow(),
1081                    }
1082                }
1083                #[inline(always)]
1084                fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> {
1085                    #c_ident {
1086                        #(#names: <#container_names as ::columnar::Borrow>::reborrow(thing.#names),)*
1087                        indexes: <::columnar::Discriminant as ::columnar::Borrow>::reborrow(thing.indexes),
1088                    }
1089                }
1090                #[inline(always)]
1091                fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> {
1092                    match thing {
1093                        #( #reborrow_ref )*
1094                    }
1095                }
1096            }
1097
1098            impl < #(#container_names : ::columnar::Container + ::columnar::Len),* > ::columnar::Container for #c_ident < #(#container_names),* > {
1099                #[inline(always)]
1100                fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: std::ops::Range<usize>) {
1101                    if !range.is_empty() {
1102                        #( let #len_idents = ::columnar::Len::len(&self.#names); )*
1103                        #( let mut #count_idents = 0usize; )*
1104                        #( let mut #start_idents = 0u64; )*
1105                        for index in range.clone() {
1106                            let (variant, offset) = other.indexes.get(index);
1107                            match variant {
1108                                #(
1109                                    #variant_indices => {
1110                                        if #count_idents == 0 { #start_idents = offset; }
1111                                        self.indexes.push(#variant_indices, (#len_idents + #count_idents) as u64);
1112                                        #count_idents += 1;
1113                                    }
1114                                )*
1115                                _ => unreachable!(),
1116                            }
1117                        }
1118                        #(
1119                            if #count_idents > 0 {
1120                                self.#names.extend_from_self(other.#names, #start_idents as usize .. #start_idents as usize + #count_idents);
1121                            }
1122                        )*
1123                    }
1124                }
1125
1126                fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone {
1127                    #( self.#names.reserve_for(selves.clone().map(|x| x.#names)); )*
1128                    self.indexes.reserve_for(selves.map(|x| x.indexes));
1129                }
1130            }
1131        }
1132    };
1133
1134    let try_unwrap = {
1135        let impl_gen = quote! { < #(#container_types),* > };
1136        let ty_gen = quote! { < #(#container_types),* > };
1137
1138        let numbers = (0u8 ..);
1139        let methods = names.iter().zip(container_types.iter()).zip(numbers).map(|((name, ctype), index)| {
1140            let try_name = syn::Ident::new(&format!("try_unwrap_{}", name), name.span());
1141            quote! {
1142                /// Returns the #name container if all elements are #name.
1143                #[inline]
1144                pub fn #try_name(&self) -> Option<&#ctype> {
1145                    if self.indexes.homogeneous() == Some(#index) { Some(&self.#name) } else { None }
1146                }
1147            }
1148        });
1149
1150        quote! {
1151            #[allow(non_snake_case)]
1152            impl #impl_gen #c_ident #ty_gen {
1153                #( #methods )*
1154            }
1155        }
1156    };
1157
1158    quote! {
1159
1160        #container_struct
1161        #reference_struct
1162
1163        #push_own
1164        #push_ref
1165        #push_new
1166
1167        #index_own
1168        #index_ref
1169        #length
1170        #clear
1171
1172        #as_bytes
1173        #from_bytes
1174
1175        #columnar_impl
1176
1177        #try_unwrap
1178
1179    }.into()
1180}
1181
1182/// A derivation for an enum type with no fields in any of its variants.
1183#[allow(unused)]
1184fn derive_tags(name: &syn::Ident, _generics: &syn:: Generics, data_enum: syn::DataEnum, vis: syn::Visibility) -> proc_macro::TokenStream {
1185
1186    let c_name = format!("{}Container", name);
1187    let c_ident = syn::Ident::new(&c_name, name.span());
1188
1189    let names: Vec<&syn::Ident> =
1190    data_enum
1191        .variants
1192        .iter()
1193        .map(|variant| &variant.ident)
1194        .collect();
1195
1196    let indices: &Vec<u8> = &(0 .. names.len()).map(|x| x as u8).collect();
1197
1198    // Bit silly, but to help us fit in a byte and reign in bloat.
1199    assert!(names.len() <= 256, "Too many variants for enum");
1200
1201    #[cfg(feature = "serde")]
1202    let derive = quote! { #[derive(Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize)] };
1203    #[cfg(not(feature = "serde"))]
1204    let derive = quote! { #[derive(Copy, Clone, Debug, Default)] };
1205
1206    quote! {
1207        /// Derived columnar container for all-unit enum.
1208        #derive
1209        #vis struct #c_ident <CVar = Vec<u8>> {
1210            /// Container for variant.
1211            pub variant: CVar,
1212        }
1213
1214        impl<CV: ::columnar::common::PushIndexAs<u8>> ::columnar::Push<#name> for #c_ident<CV> {
1215            #[inline]
1216            fn push(&mut self, item: #name) {
1217                match item {
1218                    #( #name::#names => self.variant.push(&#indices), )*
1219                }
1220            }
1221        }
1222
1223        impl<'columnar> ::columnar::Push<&'columnar #name> for #c_ident {
1224            #[inline]
1225            fn push(&mut self, item: &'columnar #name) {
1226                match *item {
1227                    #( #name::#names => self.variant.push(#indices), )*
1228                }
1229            }
1230        }
1231
1232        impl<CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for #c_ident <CVar> {
1233            type Ref = #name;
1234            #[inline(always)]
1235            fn get(&self, index: usize) -> Self::Ref {
1236                match self.variant.index_as(index) {
1237                    #( #indices => #name::#names, )*
1238                    x => panic!("Unacceptable discriminant found: {:?}", x),
1239                }
1240            }
1241        }
1242
1243        impl<'columnar, CVar: ::columnar::Len + ::columnar::IndexAs<u8>> ::columnar::Index for &'columnar #c_ident <CVar> {
1244            type Ref = #name;
1245            #[inline(always)]
1246            fn get(&self, index: usize) -> Self::Ref {
1247                match self.variant.index_as(index) {
1248                    #( #indices => #name::#names, )*
1249                    x => panic!("Unacceptable discriminant found: {:?}", x),
1250                }
1251            }
1252        }
1253
1254        impl<CVar: ::columnar::Clear> ::columnar::Clear for #c_ident <CVar> {
1255            #[inline(always)]
1256            fn clear(&mut self) {
1257                self.variant.clear();
1258            }
1259        }
1260
1261        impl<CVar: ::columnar::Len> ::columnar::Len for #c_ident <CVar> {
1262            #[inline(always)]
1263            fn len(&self) -> usize {
1264                self.variant.len()
1265            }
1266        }
1267
1268        impl<'a, CVar: ::columnar::AsBytes<'a>> ::columnar::AsBytes<'a> for #c_ident <CVar> {
1269            const SLICE_COUNT: usize = CVar::SLICE_COUNT;
1270            #[inline]
1271            fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
1272                debug_assert!(index < Self::SLICE_COUNT);
1273                self.variant.get_byte_slice(index)
1274            }
1275        }
1276
1277        impl<'columnar, CVar: ::columnar::FromBytes<'columnar>> ::columnar::FromBytes<'columnar> for #c_ident <CVar> {
1278            const SLICE_COUNT: usize = CVar::SLICE_COUNT;
1279            #[inline(always)]
1280            fn from_bytes(bytes: &mut impl Iterator<Item=&'columnar [u8]>) -> Self {
1281                Self { variant: ::columnar::FromBytes::from_bytes(bytes) }
1282            }
1283            #[inline(always)]
1284            fn from_store(store: &::columnar::bytes::indexed::DecodedStore<'columnar>, offset: &mut usize) -> Self {
1285                Self { variant: ::columnar::FromBytes::from_store(store, offset) }
1286            }
1287            fn element_sizes(sizes: &mut Vec<usize>) -> ::core::result::Result<(), String> {
1288                CVar::element_sizes(sizes)
1289            }
1290        }
1291
1292        impl ::columnar::Columnar for #name {
1293            #[inline(always)]
1294            fn copy_from<'a>(&mut self, other: ::columnar::Ref<'a, Self>) { *self = other; }
1295            #[inline(always)]
1296            fn into_owned<'a>(other: ::columnar::Ref<'a, Self>) -> Self { other }
1297            type Container = #c_ident;
1298        }
1299
1300        impl<CV: ::columnar::common::BorrowIndexAs<u8>> ::columnar::Borrow for #c_ident <CV> {
1301            type Ref<'a> = #name;
1302            type Borrowed<'a> = #c_ident < CV::Borrowed<'a> > where CV: 'a;
1303            #[inline(always)]
1304            fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
1305                #c_ident {
1306                    variant: self.variant.borrow()
1307                }
1308            }
1309            #[inline(always)]
1310            fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> {
1311                #c_ident {
1312                    variant: <CV as ::columnar::Borrow>::reborrow(thing.variant),
1313                }
1314            }
1315            #[inline(always)]
1316            fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> { thing }
1317        }
1318
1319        impl<CV: ::columnar::common::PushIndexAs<u8>> ::columnar::Container for #c_ident <CV> {
1320            #[inline(always)]
1321            fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: std::ops::Range<usize>) {
1322                self.variant.extend_from_self(other.variant, range);
1323            }
1324
1325            fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone {
1326                self.variant.reserve_for(selves.map(|x| x.variant));
1327            }
1328        }
1329    }.into()
1330}