@@ -589,15 +589,13 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
589589 /// Derived columnar container for an enum.
590590 #derive
591591 #[ allow( non_snake_case) ]
592- #vis struct #c_ident < #( #container_types, ) * CVar = Vec <u8 >, COff = Vec <u64 >, >{
592+ #vis struct #c_ident < #( #container_types, ) * CVar = Vec <u8 >, COff = Vec <u64 >, CC = u64 , >{
593593 #(
594594 /// Container for #names.
595595 pub #names : #container_types,
596596 ) *
597- /// Container for variant.
598- pub variant: CVar ,
599- /// Container for offset.
600- pub offset: COff ,
597+ /// Discriminant tracking for variants.
598+ pub indexes: :: columnar:: Discriminant <CVar , COff , CC >,
601599 }
602600 }
603601 } ;
@@ -641,9 +639,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
641639 syn:: Fields :: Unit => {
642640 quote ! {
643641 #name:: #variant => {
644- self . offset . push( self . #variant. len( ) as u64 ) ;
642+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
645643 self . #variant. push( ( ) ) ;
646- self . variant. push( #index as u8 ) ;
647644 }
648645 }
649646 }
@@ -655,9 +652,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
655652
656653 quote ! {
657654 #name:: #variant( #( #temp_names) , * ) => {
658- self . offset . push( self . #variant. len( ) as u64 ) ;
655+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
659656 self . #variant. push( ( #( #temp_names) , * ) ) ;
660- self . variant. push( #index as u8 ) ;
661657 } ,
662658 }
663659 }
@@ -696,9 +692,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
696692 syn:: Fields :: Unit => {
697693 quote ! {
698694 #name:: #variant => {
699- self . offset . push( self . #variant. len( ) as u64 ) ;
695+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
700696 self . #variant. push( ( ) ) ;
701- self . variant. push( #index as u8 ) ;
702697 }
703698 }
704699 }
@@ -710,9 +705,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
710705
711706 quote ! {
712707 #name:: #variant( #( #temp_names) , * ) => {
713- self . offset . push( self . #variant. len( ) as u64 ) ;
708+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
714709 self . #variant. push( ( #( #temp_names) , * ) ) ;
715- self . variant. push( #index as u8 ) ;
716710 } ,
717711 }
718712 }
@@ -763,9 +757,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
763757 match item {
764758 #(
765759 #r_ident:: #names( x) => {
766- self . offset . push( self . #names. len( ) as u64 ) ;
760+ self . indexes . push( #numbers as u8 , self . #names. len( ) as u64 ) ;
767761 self . #names. push( x) ;
768- self . variant. push( #numbers as u8 ) ;
769762 } ,
770763 ) *
771764 }
@@ -775,9 +768,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
775768 } ;
776769
777770 let index_own = {
778- let impl_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
779- let ty_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
780- let where_clause = quote ! { where #( #container_types: :: columnar:: Index , ) * CVal : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs <u64 > } ;
771+ let impl_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
772+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
773+ let where_clause = quote ! { where #( #container_types: :: columnar:: Index , ) * CVar : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs < u64 > , CC : :: columnar :: common :: index :: CopyAs <u64 > } ;
781774
782775 let index_type = quote ! { #r_ident < #( <#container_types as :: columnar:: Index >:: Ref , ) * > } ;
783776
@@ -789,8 +782,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
789782 type Ref = #index_type;
790783 #[ inline( always) ]
791784 fn get( & self , index: usize ) -> Self :: Ref {
792- match self . variant. index_as( index) as usize {
793- #( #numbers => #r_ident:: #names( self . #names. get( self . offset. index_as( index) as usize ) ) , ) *
785+ let ( variant, offset) = self . indexes. get( index) ;
786+ match variant as usize {
787+ #( #numbers => #r_ident:: #names( self . #names. get( offset as usize ) ) , ) *
794788 x => panic!( "Unacceptable discriminant found: {:?}" , x) ,
795789 }
796790 }
@@ -799,9 +793,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
799793 } ;
800794
801795 let index_ref = {
802- let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVal , COff > } ;
803- let ty_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
804- let where_clause = quote ! { where #( & ' columnar #container_types: :: columnar:: Index , ) * CVal : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs <u64 > } ;
796+ let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff , CC > } ;
797+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
798+ let where_clause = quote ! { where #( & ' columnar #container_types: :: columnar:: Index , ) * CVar : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs < u64 > , CC : :: columnar :: common :: index :: CopyAs <u64 > } ;
805799
806800 let index_type = quote ! { #r_ident < #( <& ' columnar #container_types as :: columnar:: Index >:: Ref , ) * > } ;
807801
@@ -813,8 +807,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
813807 type Ref = #index_type;
814808 #[ inline( always) ]
815809 fn get( & self , index: usize ) -> Self :: Ref {
816- match self . variant. index_as( index) as usize {
817- #( #numbers => #r_ident:: #names( ( & self . #names) . get( self . offset. index_as( index) as usize ) ) , ) *
810+ let ( variant, offset) = self . indexes. get( index) ;
811+ match variant as usize {
812+ #( #numbers => #r_ident:: #names( ( & self . #names) . get( offset as usize ) ) , ) *
818813 x => panic!( "Unacceptable discriminant found: {:?}" , x) ,
819814 }
820815 }
@@ -833,42 +828,40 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
833828 #[ inline( always) ]
834829 fn clear( & mut self ) {
835830 #( self . #names. clear( ) ; ) *
836- self . variant. clear( ) ;
837- self . offset. clear( ) ;
831+ self . indexes. clear( ) ;
838832 }
839833 }
840834 }
841835 } ;
842836
843837 let length = {
844838
845- let impl_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
846- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
839+ let impl_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
840+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
847841
848842 quote ! {
849- impl #impl_gen :: columnar:: Len for #c_ident #ty_gen where CVar : :: columnar:: Len {
843+ impl #impl_gen :: columnar:: Len for #c_ident #ty_gen where CVar : :: columnar:: Len , CC : :: columnar :: common :: index :: CopyAs < u64 > {
850844 #[ inline( always) ]
851845 fn len( & self ) -> usize {
852- self . variant . len( )
846+ self . indexes . len( )
853847 }
854848 }
855849 }
856850 } ;
857851
858852 let as_bytes = {
859853
860- let impl_gen = quote ! { < ' a, #( #container_types, ) * CVar , COff > } ;
861- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
862- let where_clause = quote ! { where #( #container_types: :: columnar:: AsBytes <' a>, ) * CVar : :: columnar:: AsBytes < ' a> , COff : :: columnar:: AsBytes <' a> } ;
854+ let impl_gen = quote ! { < ' a, #( #container_types, ) * CVar , COff , CC > } ;
855+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
856+ let where_clause = quote ! { where #( #container_types: :: columnar:: AsBytes <' a>, ) * :: columnar:: Discriminant < CVar , COff , CC > : :: columnar:: AsBytes <' a> } ;
863857
864858 quote ! {
865859 impl #impl_gen :: columnar:: AsBytes <' a> for #c_ident #ty_gen #where_clause {
866860 #[ inline( always) ]
867861 fn as_bytes( & self ) -> impl Iterator <Item =( u64 , & ' a [ u8 ] ) > {
868862 let iter = None . into_iter( ) ;
869863 #( let iter = :: columnar:: chain( iter, self . #names. as_bytes( ) ) ; ) *
870- let iter = :: columnar:: chain( iter, self . variant. as_bytes( ) ) ;
871- let iter = :: columnar:: chain( iter, self . offset. as_bytes( ) ) ;
864+ let iter = :: columnar:: chain( iter, self . indexes. as_bytes( ) ) ;
872865 iter
873866 }
874867 }
@@ -877,9 +870,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
877870
878871 let from_bytes = {
879872
880- let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff > } ;
881- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
882- let where_clause = quote ! { where #( #container_types: :: columnar:: FromBytes <' columnar>, ) * CVar : :: columnar:: FromBytes < ' columnar> , COff : :: columnar:: FromBytes <' columnar> } ;
873+ let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff , CC > } ;
874+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
875+ let where_clause = quote ! { where #( #container_types: :: columnar:: FromBytes <' columnar>, ) * :: columnar:: Discriminant < CVar , COff , CC > : :: columnar:: FromBytes <' columnar> } ;
883876
884877 quote ! {
885878 #[ allow( non_snake_case) ]
@@ -888,8 +881,7 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
888881 fn from_bytes( bytes: & mut impl Iterator <Item =& ' columnar [ u8 ] >) -> Self {
889882 Self {
890883 #( #names: :: columnar:: FromBytes :: from_bytes( bytes) , ) *
891- variant: :: columnar:: FromBytes :: from_bytes( bytes) ,
892- offset: :: columnar:: FromBytes :: from_bytes( bytes) ,
884+ indexes: :: columnar:: FromBytes :: from_bytes( bytes) ,
893885 }
894886 }
895887 }
@@ -999,21 +991,19 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
999991
1000992 impl < #( #container_names : :: columnar:: Borrow ) , * > :: columnar:: Borrow for #c_ident < #( #container_names) , * > {
1001993 type Ref <' a> = #r_ident < #( <#container_names as :: columnar:: Borrow >:: Ref <' a> , ) * > where Self : ' a, #( #container_names: ' a, ) * ;
1002- type Borrowed <' a> = #c_ident < #( < #container_names as :: columnar:: Borrow >:: Borrowed <' a>, ) * & ' a [ u8 ] , & ' a [ u64 ] > where #( #container_names: ' a, ) * ;
994+ type Borrowed <' a> = #c_ident < #( < #container_names as :: columnar:: Borrow >:: Borrowed <' a>, ) * & ' a [ u8 ] , & ' a [ u64 ] , & ' a u64 > where #( #container_names: ' a, ) * ;
1003995 #[ inline( always) ]
1004996 fn borrow<' a>( & ' a self ) -> Self :: Borrowed <' a> {
1005997 #c_ident {
1006998 #( #names: self . #names. borrow( ) , ) *
1007- variant: self . variant. borrow( ) ,
1008- offset: self . offset. borrow( ) ,
999+ indexes: self . indexes. borrow( ) ,
10091000 }
10101001 }
10111002 #[ inline( always) ]
10121003 fn reborrow<' b, ' a: ' b>( thing: Self :: Borrowed <' a>) -> Self :: Borrowed <' b> {
10131004 #c_ident {
10141005 #( #names: <#container_names as :: columnar:: Borrow >:: reborrow( thing. #names) , ) *
1015- variant: <Vec <u8 > as :: columnar:: Borrow >:: reborrow( thing. variant) ,
1016- offset: <Vec <u64 > as :: columnar:: Borrow >:: reborrow( thing. offset) ,
1006+ indexes: <:: columnar:: Discriminant as :: columnar:: Borrow >:: reborrow( thing. indexes) ,
10171007 }
10181008 }
10191009 #[ inline( always) ]
@@ -1029,13 +1019,36 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
10291019
10301020 fn reserve_for<' a, I >( & mut self , selves: I ) where Self : ' a, I : Iterator <Item = Self :: Borrowed <' a>> + Clone {
10311021 #( self . #names. reserve_for( selves. clone( ) . map( |x| x. #names) ) ; ) *
1032- self . variant. reserve_for( selves. clone( ) . map( |x| x. variant) ) ;
1033- self . offset. reserve_for( selves. map( |x| x. offset) ) ;
1022+ self . indexes. reserve_for( selves. map( |x| x. indexes) ) ;
10341023 }
10351024 }
10361025 }
10371026 } ;
10381027
1028+ let try_unwrap = {
1029+ let impl_gen = quote ! { < #( #container_types) , * > } ;
1030+ let ty_gen = quote ! { < #( #container_types) , * > } ;
1031+
1032+ let numbers = ( 0u8 ..) ;
1033+ let methods = names. iter ( ) . zip ( container_types. iter ( ) ) . zip ( numbers) . map ( |( ( name, ctype) , index) | {
1034+ let try_name = syn:: Ident :: new ( & format ! ( "try_unwrap_{}" , name) , name. span ( ) ) ;
1035+ quote ! {
1036+ /// Returns the #name container if all elements are #name.
1037+ #[ inline]
1038+ pub fn #try_name( & self ) -> Option <& #ctype> {
1039+ if self . indexes. homogeneous( ) == Some ( #index) { Some ( & self . #name) } else { None }
1040+ }
1041+ }
1042+ } ) ;
1043+
1044+ quote ! {
1045+ #[ allow( non_snake_case) ]
1046+ impl #impl_gen #c_ident #ty_gen {
1047+ #( #methods ) *
1048+ }
1049+ }
1050+ } ;
1051+
10391052 quote ! {
10401053
10411054 #container_struct
@@ -1055,6 +1068,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
10551068
10561069 #columnar_impl
10571070
1071+ #try_unwrap
1072+
10581073 } . into ( )
10591074}
10601075
0 commit comments