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 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 #[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 #derive
80 #vis struct #c_ident < #(#container_types),* >{
81 #(
82 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 #[derive(Copy, Clone, Debug)]
107 #attr
108 #vis struct #r_ident #ty_gen {
109 #(
110 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 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 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 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 #[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 let destructure_self =
342 if named { quote! { let #name { #(#names),* } = self; } }
343 else { quote! { let #name ( #(#names),* ) = self; } };
344
345 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
423fn 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 #derive
442 #vis struct #c_ident<CW = u64> {
443 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 #[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#[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 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 assert!(variants.len() <= 256, "Too many variants for enum");
569
570 let names = &variants.iter().map(|(ident, _)| ident).collect::<Vec<_>>();
571
572 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 #derive
587 #[allow(non_snake_case)]
588 #vis struct #c_ident < #(#container_types,)* CVar = Vec<u8>, COff = Vec<u64>, >{
589 #(
590 pub #names : #container_types,
592 )*
593 pub variant: CVar,
595 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 #[derive(Copy, Clone, Debug)]
620 #attr
621 #vis enum #r_ident #ty_gen {
622 #(
623 #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 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 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 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 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 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 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 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 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#[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 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 #derive
1082 #vis struct #c_ident <CVar = Vec<u8>> {
1083 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 #[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 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}