@@ -753,66 +753,43 @@ fn as_roaring(buf: &[u8]) -> Option<&[u8]> {
753753 }
754754}
755755
756- struct SmallReader < ' a > {
757- len : usize ,
758- values : & ' a [ u8 ] ,
756+ struct SmallReader {
757+ values : SmallBitmap ,
759758}
760759
761- impl < ' a > SmallReader < ' a > {
762- fn new ( buf : & ' a [ u8 ] ) -> Result < Self > {
760+ impl SmallReader {
761+ // decode_small_payload returns raw bytes which may contain duplicates or be
762+ // unsorted; decode_small_values deduplicates and sorts via small_insert, so
763+ // that binary-search and two-pointer merge agree with deserialize_bitmap.
764+ fn new ( buf : & [ u8 ] ) -> Result < Self > {
763765 let payload = & buf[ HYBRID_HEADER_LEN ..] ;
764- let ( len, bytes) = decode_small_payload ( payload) ?;
765- Ok ( Self { len, values : bytes } )
766+ Ok ( Self {
767+ values : decode_small_values ( payload) ?,
768+ } )
766769 }
767770
768771 fn len ( & self ) -> usize {
769- self . len
770- }
771-
772- fn is_empty ( & self ) -> bool {
773- self . len == 0
774- }
775-
776- fn get ( & self , i : usize ) -> u64 {
777- read_u64_le ( & self . values [ i * 8 ..i * 8 + 8 ] )
772+ self . values . len ( )
778773 }
779774
780775 fn first ( & self ) -> Option < u64 > {
781- if self . is_empty ( ) {
782- None
783- } else {
784- Some ( self . get ( 0 ) )
785- }
776+ self . values . first ( ) . copied ( )
786777 }
787778
788779 fn last ( & self ) -> Option < u64 > {
789- if self . is_empty ( ) {
790- None
791- } else {
792- Some ( self . get ( self . len - 1 ) )
793- }
780+ self . values . last ( ) . copied ( )
794781 }
795782
796783 fn contains ( & self , value : u64 ) -> bool {
797- let mut lo = 0 ;
798- let mut hi = self . len ;
799- while lo < hi {
800- let mid = lo + ( hi - lo) / 2 ;
801- match self . get ( mid) . cmp ( & value) {
802- std:: cmp:: Ordering :: Less => lo = mid + 1 ,
803- std:: cmp:: Ordering :: Greater => hi = mid,
804- std:: cmp:: Ordering :: Equal => return true ,
805- }
806- }
807- false
784+ self . values . binary_search ( & value) . is_ok ( )
808785 }
809786
810787 fn has_any_with ( & self , other : & SmallReader ) -> bool {
811788 let mut i = 0 ;
812789 let mut j = 0 ;
813- while i < self . len && j < other. len {
814- let lv = self . get ( i ) ;
815- let rv = other. get ( j ) ;
790+ while i < self . len ( ) && j < other. len ( ) {
791+ let lv = self . values [ i ] ;
792+ let rv = other. values [ j ] ;
816793 if lv < rv {
817794 i += 1 ;
818795 } else if rv < lv {
@@ -825,17 +802,17 @@ impl<'a> SmallReader<'a> {
825802 }
826803
827804 fn has_all_with ( & self , other : & SmallReader ) -> bool {
828- if self . len < other. len {
805+ if self . len ( ) < other. len ( ) {
829806 return false ;
830807 }
831808 let mut i = 0 ;
832809 let mut j = 0 ;
833- while j < other. len {
834- if i >= self . len {
810+ while j < other. len ( ) {
811+ if i >= self . len ( ) {
835812 return false ;
836813 }
837- let lv = self . get ( i ) ;
838- let rv = other. get ( j ) ;
814+ let lv = self . values [ i ] ;
815+ let rv = other. values [ j ] ;
839816 if lv < rv {
840817 i += 1 ;
841818 } else if lv == rv {
@@ -947,13 +924,14 @@ pub fn bitmap_has_all(lhs: &[u8], rhs: &[u8]) -> Result<bool> {
947924 return Ok ( lhs. has_all_with ( & rhs) ) ;
948925 }
949926
950- // Fast path: HybridSmall lhs, Legacy rhs — cardinality check
951- // We need to check cardinality here because: (1) it might be a legacy tree and (2) sometimes
952- // we don't try demote HybridBitmap after reduce its cardinality immediately.
927+ // Fast path: HybridSmall lhs, HybridLarge or Legacy rhs cardinality check
928+ // We need to check cardinality here because: (1) it might be a legacy tree,
929+ // and (2) we don't always demote HybridBitmap after reducing its cardinality immediately.
953930 if as_roaring ( lhs) . is_none ( ) && as_roaring ( rhs) . is_some ( ) {
954931 let lhs_small = SmallReader :: new ( lhs) ?;
932+ let rhs_roaring = as_roaring ( rhs) . unwrap ( ) ;
955933 // Fast path: rhs has more values than lhs, impossible to contain
956- if reader:: bitmap_len_above ( rhs , lhs_small. len ( ) ) ? {
934+ if reader:: bitmap_len_above ( rhs_roaring , lhs_small. len ( ) ) ? {
957935 return Ok ( false ) ;
958936 }
959937 // rhs has <= lhs_small.len() values, but still need to check containment
@@ -966,7 +944,7 @@ pub fn bitmap_has_all(lhs: &[u8], rhs: &[u8]) -> Result<bool> {
966944 let roaring_buf = as_roaring ( lhs) . unwrap ( ) ;
967945 let rhs_small = SmallReader :: new ( rhs) ?;
968946 for i in 0 ..rhs_small. len ( ) {
969- if !reader:: bitmap_contains ( roaring_buf, rhs_small. get ( i ) ) ? {
947+ if !reader:: bitmap_contains ( roaring_buf, rhs_small. values [ i ] ) ? {
970948 return Ok ( false ) ;
971949 }
972950 }
@@ -1000,7 +978,7 @@ pub fn bitmap_has_any(lhs: &[u8], rhs: &[u8]) -> Result<bool> {
1000978 ( as_roaring ( rhs) . unwrap ( ) , SmallReader :: new ( lhs) ?)
1001979 } ;
1002980 for i in 0 ..small. len ( ) {
1003- if reader:: bitmap_contains ( roaring_buf, small. get ( i ) ) ? {
981+ if reader:: bitmap_contains ( roaring_buf, small. values [ i ] ) ? {
1004982 return Ok ( true ) ;
1005983 }
1006984 }
0 commit comments