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