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