@@ -604,15 +604,13 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
604604 /// Derived columnar container for an enum.
605605 #derive
606606 #[ allow( non_snake_case) ]
607- #vis struct #c_ident < #( #container_types, ) * CVar = Vec <u8 >, COff = Vec <u64 >, >{
607+ #vis struct #c_ident < #( #container_types, ) * CVar = Vec <u8 >, COff = Vec <u64 >, CC = u64 , >{
608608 #(
609609 /// Container for #names.
610610 pub #names : #container_types,
611611 ) *
612- /// Container for variant.
613- pub variant: CVar ,
614- /// Container for offset.
615- pub offset: COff ,
612+ /// Discriminant tracking for variants.
613+ pub indexes: :: columnar:: Discriminant <CVar , COff , CC >,
616614 }
617615 }
618616 } ;
@@ -656,9 +654,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
656654 syn:: Fields :: Unit => {
657655 quote ! {
658656 #name:: #variant => {
659- self . offset . push( self . #variant. len( ) as u64 ) ;
657+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
660658 self . #variant. push( ( ) ) ;
661- self . variant. push( #index as u8 ) ;
662659 }
663660 }
664661 }
@@ -670,9 +667,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
670667
671668 quote ! {
672669 #name:: #variant( #( #temp_names) , * ) => {
673- self . offset . push( self . #variant. len( ) as u64 ) ;
670+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
674671 self . #variant. push( ( #( #temp_names) , * ) ) ;
675- self . variant. push( #index as u8 ) ;
676672 } ,
677673 }
678674 }
@@ -711,9 +707,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
711707 syn:: Fields :: Unit => {
712708 quote ! {
713709 #name:: #variant => {
714- self . offset . push( self . #variant. len( ) as u64 ) ;
710+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
715711 self . #variant. push( ( ) ) ;
716- self . variant. push( #index as u8 ) ;
717712 }
718713 }
719714 }
@@ -725,9 +720,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
725720
726721 quote ! {
727722 #name:: #variant( #( #temp_names) , * ) => {
728- self . offset . push( self . #variant. len( ) as u64 ) ;
723+ self . indexes . push( #index as u8 , self . #variant. len( ) as u64 ) ;
729724 self . #variant. push( ( #( #temp_names) , * ) ) ;
730- self . variant. push( #index as u8 ) ;
731725 } ,
732726 }
733727 }
@@ -778,9 +772,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
778772 match item {
779773 #(
780774 #r_ident:: #names( x) => {
781- self . offset . push( self . #names. len( ) as u64 ) ;
775+ self . indexes . push( #numbers as u8 , self . #names. len( ) as u64 ) ;
782776 self . #names. push( x) ;
783- self . variant. push( #numbers as u8 ) ;
784777 } ,
785778 ) *
786779 }
@@ -790,9 +783,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
790783 } ;
791784
792785 let index_own = {
793- let impl_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
794- let ty_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
795- let where_clause = quote ! { where #( #container_types: :: columnar:: Index , ) * CVal : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs <u64 > } ;
786+ let impl_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
787+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
788+ 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 > } ;
796789
797790 let index_type = quote ! { #r_ident < #( <#container_types as :: columnar:: Index >:: Ref , ) * > } ;
798791
@@ -804,8 +797,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
804797 type Ref = #index_type;
805798 #[ inline( always) ]
806799 fn get( & self , index: usize ) -> Self :: Ref {
807- match self . variant. index_as( index) as usize {
808- #( #numbers => #r_ident:: #names( self . #names. get( self . offset. index_as( index) as usize ) ) , ) *
800+ let ( variant, offset) = self . indexes. get( index) ;
801+ match variant as usize {
802+ #( #numbers => #r_ident:: #names( self . #names. get( offset as usize ) ) , ) *
809803 x => panic!( "Unacceptable discriminant found: {:?}" , x) ,
810804 }
811805 }
@@ -814,9 +808,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
814808 } ;
815809
816810 let index_ref = {
817- let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVal , COff > } ;
818- let ty_gen = quote ! { < #( #container_types, ) * CVal , COff > } ;
819- let where_clause = quote ! { where #( & ' columnar #container_types: :: columnar:: Index , ) * CVal : :: columnar:: Len + :: columnar:: IndexAs <u8 >, COff : :: columnar:: Len + :: columnar:: IndexAs <u64 > } ;
811+ let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff , CC > } ;
812+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
813+ 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 > } ;
820814
821815 let index_type = quote ! { #r_ident < #( <& ' columnar #container_types as :: columnar:: Index >:: Ref , ) * > } ;
822816
@@ -828,8 +822,9 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
828822 type Ref = #index_type;
829823 #[ inline( always) ]
830824 fn get( & self , index: usize ) -> Self :: Ref {
831- match self . variant. index_as( index) as usize {
832- #( #numbers => #r_ident:: #names( ( & self . #names) . get( self . offset. index_as( index) as usize ) ) , ) *
825+ let ( variant, offset) = self . indexes. get( index) ;
826+ match variant as usize {
827+ #( #numbers => #r_ident:: #names( ( & self . #names) . get( offset as usize ) ) , ) *
833828 x => panic!( "Unacceptable discriminant found: {:?}" , x) ,
834829 }
835830 }
@@ -848,42 +843,40 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
848843 #[ inline( always) ]
849844 fn clear( & mut self ) {
850845 #( self . #names. clear( ) ; ) *
851- self . variant. clear( ) ;
852- self . offset. clear( ) ;
846+ self . indexes. clear( ) ;
853847 }
854848 }
855849 }
856850 } ;
857851
858852 let length = {
859853
860- let impl_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
861- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
854+ let impl_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
855+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
862856
863857 quote ! {
864- impl #impl_gen :: columnar:: Len for #c_ident #ty_gen where CVar : :: columnar:: Len {
858+ impl #impl_gen :: columnar:: Len for #c_ident #ty_gen where CVar : :: columnar:: Len , CC : :: columnar :: common :: index :: CopyAs < u64 > {
865859 #[ inline( always) ]
866860 fn len( & self ) -> usize {
867- self . variant . len( )
861+ self . indexes . len( )
868862 }
869863 }
870864 }
871865 } ;
872866
873867 let as_bytes = {
874868
875- let impl_gen = quote ! { < ' a, #( #container_types, ) * CVar , COff > } ;
876- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
877- let where_clause = quote ! { where #( #container_types: :: columnar:: AsBytes <' a>, ) * CVar : :: columnar:: AsBytes < ' a> , COff : :: columnar:: AsBytes <' a> } ;
869+ let impl_gen = quote ! { < ' a, #( #container_types, ) * CVar , COff , CC > } ;
870+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
871+ let where_clause = quote ! { where #( #container_types: :: columnar:: AsBytes <' a>, ) * :: columnar:: Discriminant < CVar , COff , CC > : :: columnar:: AsBytes <' a> } ;
878872
879873 quote ! {
880874 impl #impl_gen :: columnar:: AsBytes <' a> for #c_ident #ty_gen #where_clause {
881875 #[ inline( always) ]
882876 fn as_bytes( & self ) -> impl Iterator <Item =( u64 , & ' a [ u8 ] ) > {
883877 let iter = None . into_iter( ) ;
884878 #( let iter = :: columnar:: chain( iter, self . #names. as_bytes( ) ) ; ) *
885- let iter = :: columnar:: chain( iter, self . variant. as_bytes( ) ) ;
886- let iter = :: columnar:: chain( iter, self . offset. as_bytes( ) ) ;
879+ let iter = :: columnar:: chain( iter, self . indexes. as_bytes( ) ) ;
887880 iter
888881 }
889882 }
@@ -892,20 +885,19 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
892885
893886 let from_bytes = {
894887
895- let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff > } ;
896- let ty_gen = quote ! { < #( #container_types, ) * CVar , COff > } ;
897- let where_clause = quote ! { where #( #container_types: :: columnar:: FromBytes <' columnar>, ) * CVar : :: columnar:: FromBytes < ' columnar> , COff : :: columnar:: FromBytes <' columnar> } ;
888+ let impl_gen = quote ! { < ' columnar, #( #container_types, ) * CVar , COff , CC > } ;
889+ let ty_gen = quote ! { < #( #container_types, ) * CVar , COff , CC > } ;
890+ let where_clause = quote ! { where #( #container_types: :: columnar:: FromBytes <' columnar>, ) * :: columnar:: Discriminant < CVar , COff , CC > : :: columnar:: FromBytes <' columnar> } ;
898891
899892 quote ! {
900893 #[ allow( non_snake_case) ]
901894 impl #impl_gen :: columnar:: FromBytes <' columnar> for #c_ident #ty_gen #where_clause {
902- const SLICE_COUNT : usize = 0 #( + <#container_types>:: SLICE_COUNT ) * + CVar :: SLICE_COUNT + COff :: SLICE_COUNT ;
895+ const SLICE_COUNT : usize = 0 #( + <#container_types>:: SLICE_COUNT ) * + < :: columnar :: Discriminant < CVar , COff , CC >> :: SLICE_COUNT ;
903896 #[ inline( always) ]
904897 fn from_bytes( bytes: & mut impl Iterator <Item =& ' columnar [ u8 ] >) -> Self {
905898 Self {
906899 #( #names: :: columnar:: FromBytes :: from_bytes( bytes) , ) *
907- variant: :: columnar:: FromBytes :: from_bytes( bytes) ,
908- offset: :: columnar:: FromBytes :: from_bytes( bytes) ,
900+ indexes: :: columnar:: FromBytes :: from_bytes( bytes) ,
909901 }
910902 }
911903 #[ inline( always) ]
@@ -915,10 +907,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
915907 let #names = <#container_types>:: from_byte_slices( & bytes[ _offset .. _offset + <#container_types>:: SLICE_COUNT ] ) ;
916908 _offset += <#container_types>:: SLICE_COUNT ;
917909 ) *
918- let variant = CVar :: from_byte_slices( & bytes[ _offset .. _offset + CVar :: SLICE_COUNT ] ) ;
919- _offset += CVar :: SLICE_COUNT ;
920- let offset = COff :: from_byte_slices( & bytes[ _offset ..] ) ;
921- Self { #( #names, ) * variant, offset }
910+ let indexes = <:: columnar:: Discriminant <CVar , COff , CC >>:: from_byte_slices( & bytes[ _offset ..] ) ;
911+ Self { #( #names, ) * indexes }
922912 }
923913 }
924914 }
@@ -1027,21 +1017,19 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
10271017
10281018 impl < #( #container_names : :: columnar:: Borrow ) , * > :: columnar:: Borrow for #c_ident < #( #container_names) , * > {
10291019 type Ref <' a> = #r_ident < #( <#container_names as :: columnar:: Borrow >:: Ref <' a> , ) * > where Self : ' a, #( #container_names: ' a, ) * ;
1030- type Borrowed <' a> = #c_ident < #( < #container_names as :: columnar:: Borrow >:: Borrowed <' a>, ) * & ' a [ u8 ] , & ' a [ u64 ] > where #( #container_names: ' a, ) * ;
1020+ type Borrowed <' a> = #c_ident < #( < #container_names as :: columnar:: Borrow >:: Borrowed <' a>, ) * & ' a [ u8 ] , & ' a [ u64 ] , & ' a u64 > where #( #container_names: ' a, ) * ;
10311021 #[ inline( always) ]
10321022 fn borrow<' a>( & ' a self ) -> Self :: Borrowed <' a> {
10331023 #c_ident {
10341024 #( #names: self . #names. borrow( ) , ) *
1035- variant: self . variant. borrow( ) ,
1036- offset: self . offset. borrow( ) ,
1025+ indexes: self . indexes. borrow( ) ,
10371026 }
10381027 }
10391028 #[ inline( always) ]
10401029 fn reborrow<' b, ' a: ' b>( thing: Self :: Borrowed <' a>) -> Self :: Borrowed <' b> {
10411030 #c_ident {
10421031 #( #names: <#container_names as :: columnar:: Borrow >:: reborrow( thing. #names) , ) *
1043- variant: <Vec <u8 > as :: columnar:: Borrow >:: reborrow( thing. variant) ,
1044- offset: <Vec <u64 > as :: columnar:: Borrow >:: reborrow( thing. offset) ,
1032+ indexes: <:: columnar:: Discriminant as :: columnar:: Borrow >:: reborrow( thing. indexes) ,
10451033 }
10461034 }
10471035 #[ inline( always) ]
@@ -1057,13 +1045,36 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
10571045
10581046 fn reserve_for<' a, I >( & mut self , selves: I ) where Self : ' a, I : Iterator <Item = Self :: Borrowed <' a>> + Clone {
10591047 #( self . #names. reserve_for( selves. clone( ) . map( |x| x. #names) ) ; ) *
1060- self . variant. reserve_for( selves. clone( ) . map( |x| x. variant) ) ;
1061- self . offset. reserve_for( selves. map( |x| x. offset) ) ;
1048+ self . indexes. reserve_for( selves. map( |x| x. indexes) ) ;
10621049 }
10631050 }
10641051 }
10651052 } ;
10661053
1054+ let try_unwrap = {
1055+ let impl_gen = quote ! { < #( #container_types) , * > } ;
1056+ let ty_gen = quote ! { < #( #container_types) , * > } ;
1057+
1058+ let numbers = ( 0u8 ..) ;
1059+ let methods = names. iter ( ) . zip ( container_types. iter ( ) ) . zip ( numbers) . map ( |( ( name, ctype) , index) | {
1060+ let try_name = syn:: Ident :: new ( & format ! ( "try_unwrap_{}" , name) , name. span ( ) ) ;
1061+ quote ! {
1062+ /// Returns the #name container if all elements are #name.
1063+ #[ inline]
1064+ pub fn #try_name( & self ) -> Option <& #ctype> {
1065+ if self . indexes. homogeneous( ) == Some ( #index) { Some ( & self . #name) } else { None }
1066+ }
1067+ }
1068+ } ) ;
1069+
1070+ quote ! {
1071+ #[ allow( non_snake_case) ]
1072+ impl #impl_gen #c_ident #ty_gen {
1073+ #( #methods ) *
1074+ }
1075+ }
1076+ } ;
1077+
10671078 quote ! {
10681079
10691080 #container_struct
@@ -1083,6 +1094,8 @@ fn derive_enum(name: &syn::Ident, generics: &syn:: Generics, data_enum: syn::Dat
10831094
10841095 #columnar_impl
10851096
1097+ #try_unwrap
1098+
10861099 } . into ( )
10871100}
10881101
0 commit comments