columnar_derive/
lib.rs

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