@@ -8,6 +8,7 @@ use extern_alloc::string::ToString;
88#[ cfg( not( feature = "std" ) ) ]
99use {
1010 core:: convert:: Infallible ,
11+ core:: hash,
1112 core:: iter,
1213 core:: mem:: MaybeUninit ,
1314 core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Not } ,
2425use {
2526 std:: alloc:: { self , Layout , handle_alloc_error} ,
2627 std:: convert:: Infallible ,
28+ std:: hash,
2729 std:: iter,
2830 std:: mem:: MaybeUninit ,
2931 std:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Not } ,
@@ -697,6 +699,86 @@ macro_rules! impl_from {
697699
698700impl_from ! ( u8 , u16 , u32 , u64 , usize ) ;
699701
702+ impl cmp:: PartialEq for SmolBitSet {
703+ fn eq ( & self , other : & Self ) -> bool {
704+ match ( self . len ( ) , other. len ( ) ) {
705+ ( 0 , 0 ) => unsafe {
706+ self . get_inline_data_unchecked ( ) == other. get_inline_data_unchecked ( )
707+ } ,
708+ ( a, b) if a == b => {
709+ let a = unsafe { self . as_slice_unchecked ( ) } ;
710+ let b = unsafe { other. as_slice_unchecked ( ) } ;
711+
712+ a == b
713+ }
714+ _ => false ,
715+ }
716+ }
717+ }
718+
719+ impl cmp:: Eq for SmolBitSet { }
720+
721+ impl cmp:: PartialOrd for SmolBitSet {
722+ fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
723+ Some ( self . cmp ( other) )
724+ }
725+ }
726+
727+ impl cmp:: Ord for SmolBitSet {
728+ fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
729+ match ( self . len ( ) , other. len ( ) ) {
730+ ( 0 , 0 ) => unsafe {
731+ self . get_inline_data_unchecked ( )
732+ . cmp ( & other. get_inline_data_unchecked ( ) )
733+ } ,
734+ ( 0 , _) => cmp:: Ordering :: Less ,
735+ ( _, 0 ) => cmp:: Ordering :: Greater ,
736+ ( a, b) if a == b => unsafe {
737+ let a = self . as_slice_unchecked ( ) ;
738+ let b = other. as_slice_unchecked ( ) ;
739+
740+ for ( a, b) in a. iter ( ) . zip ( b. iter ( ) ) . rev ( ) {
741+ let cmp = a. cmp ( b) ;
742+ if cmp != cmp:: Ordering :: Equal {
743+ return cmp;
744+ }
745+ }
746+
747+ cmp:: Ordering :: Equal
748+ } ,
749+ ( a, b) => a. cmp ( & b) ,
750+ }
751+ }
752+ }
753+
754+ impl hash:: Hash for SmolBitSet {
755+ fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
756+ if self . is_inline ( ) {
757+ unsafe { self . get_inline_data_unchecked ( ) } . hash ( state) ;
758+ return ;
759+ }
760+
761+ let hb = self . highest_set_bit ( ) ;
762+ let data = unsafe { self . as_slice_unchecked ( ) } ;
763+ for d in data. iter ( ) . take ( hb. div_ceil ( BST_BITS ) ) {
764+ d. hash ( state) ;
765+ }
766+ }
767+ }
768+
769+ impl fmt:: Debug for SmolBitSet {
770+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
771+ let data = if self . is_inline ( ) {
772+ let d = unsafe { self . get_inline_data_unchecked ( ) } ;
773+ & [ d as BitSliceType , ( d >> BST_BITS ) as BitSliceType ]
774+ } else {
775+ unsafe { self . as_slice_unchecked ( ) }
776+ } ;
777+
778+ f. debug_list ( ) . entries ( data) . finish ( )
779+ }
780+ }
781+
700782impl fmt:: Display for SmolBitSet {
701783 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
702784 if self . is_inline ( ) {
@@ -708,6 +790,31 @@ impl fmt::Display for SmolBitSet {
708790 }
709791}
710792
793+ impl fmt:: Binary for SmolBitSet {
794+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
795+ if self . is_inline ( ) {
796+ return fmt:: Binary :: fmt ( & unsafe { self . get_inline_data_unchecked ( ) } , f) ;
797+ }
798+
799+ let data = unsafe { self . as_slice_unchecked ( ) } ;
800+ let highest = self . highest_set_bit ( ) . saturating_sub ( 1 ) . div_ceil ( BST_BITS ) ;
801+
802+ let mut full_width = false ;
803+ for idx in ( 0 ..highest) . rev ( ) {
804+ let d = data[ idx] ;
805+
806+ if full_width {
807+ write ! ( f, "{d:0BST_BITS$b}" ) ?;
808+ } else {
809+ full_width = true ;
810+ fmt:: Binary :: fmt ( & d, f) ?;
811+ }
812+ }
813+
814+ Ok ( ( ) )
815+ }
816+ }
817+
711818impl TryFrom < String > for SmolBitSet {
712819 type Error = ( ) ;
713820
@@ -931,6 +1038,32 @@ mod tests {
9311038 assert_eq ! ( ( !sbs) . as_slice( ) , [ !0x0000_1234 , !0xC5C5_BEEF ] ) ;
9321039 }
9331040
1041+ #[ test]
1042+ #[ cfg( feature = "std" ) ]
1043+ fn hash ( ) {
1044+ // core does not have a default hasher
1045+ use hash:: { DefaultHasher , Hash , Hasher } ;
1046+
1047+ let a = SmolBitSet :: from ( 0xC5C5_F00Du32 ) ;
1048+ let b = SmolBitSet :: from ( 0xC5C5_F00Du32 ) ;
1049+ let mut hasher_a = DefaultHasher :: new ( ) ;
1050+ let mut hasher_b = DefaultHasher :: new ( ) ;
1051+ a. hash ( & mut hasher_a) ;
1052+ b. hash ( & mut hasher_b) ;
1053+ assert_eq ! ( hasher_a. finish( ) , hasher_b. finish( ) ) ;
1054+
1055+ let mut a = SmolBitSet :: from ( 0xFFC5_C0FF_EE00_BEEF_u64 ) ;
1056+ let mut b = SmolBitSet :: from ( 0xFFC5_C0FF_EE00_BEEF_u64 ) ;
1057+ a <<= 128u8 ;
1058+ a >>= 66u8 ;
1059+ b <<= 128u8 - 66u8 ;
1060+ let mut hasher_a = DefaultHasher :: new ( ) ;
1061+ let mut hasher_b = DefaultHasher :: new ( ) ;
1062+ a. hash ( & mut hasher_a) ;
1063+ b. hash ( & mut hasher_b) ;
1064+ assert_eq ! ( hasher_a. finish( ) , hasher_b. finish( ) ) ;
1065+ }
1066+
9341067 mod from {
9351068 use super :: * ;
9361069
@@ -1319,4 +1452,35 @@ mod tests {
13191452 }
13201453 }
13211454 }
1455+
1456+ mod cmp {
1457+ use super :: * ;
1458+
1459+ #[ test]
1460+ fn eq ( ) {
1461+ let mut a = SmolBitSet :: from ( u16:: MAX ) ;
1462+ let mut b = SmolBitSet :: from ( 0xFFFFu16 ) ;
1463+ assert_eq ! ( a, b) ;
1464+
1465+ a <<= 55 ;
1466+ assert_ne ! ( a, b) ;
1467+
1468+ b <<= 55 ;
1469+ assert_eq ! ( a, b) ;
1470+ }
1471+
1472+ #[ test]
1473+ fn ord ( ) {
1474+ let mut a = SmolBitSet :: from ( 0xBEEFu16 ) ;
1475+ let mut b = SmolBitSet :: from ( 0x00C5_F00Du32 ) ;
1476+ assert ! ( a < b) ;
1477+
1478+ a <<= 72 ;
1479+ assert ! ( a > b) ;
1480+ assert ! ( b < a) ;
1481+
1482+ b <<= 72 ;
1483+ assert ! ( a < b) ;
1484+ }
1485+ }
13221486}
0 commit comments