@@ -4,6 +4,7 @@ use std::fmt;
44use std:: iter;
55use std:: marker:: PhantomData ;
66use std:: mem;
7+ use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Not , Range , Shl } ;
78use std:: slice;
89
910#[ cfg( test) ]
@@ -1001,3 +1002,137 @@ fn word_index_and_mask<T: Idx>(elem: T) -> (usize, Word) {
10011002 let mask = 1 << ( elem % WORD_BITS ) ;
10021003 ( word_index, mask)
10031004}
1005+
1006+ /// Integral type used to represent the bit set.
1007+ pub trait FiniteBitSetTy :
1008+ BitAnd < Output = Self >
1009+ + BitAndAssign
1010+ + BitOrAssign
1011+ + Clone
1012+ + Copy
1013+ + Shl
1014+ + Not < Output = Self >
1015+ + PartialEq
1016+ + Sized
1017+ {
1018+ /// Size of the domain representable by this type, e.g. 64 for `u64`.
1019+ const DOMAIN_SIZE : u32 ;
1020+
1021+ /// Value which represents the `FiniteBitSet` having every bit set.
1022+ const FILLED : Self ;
1023+ /// Value which represents the `FiniteBitSet` having no bits set.
1024+ const EMPTY : Self ;
1025+
1026+ /// Value for one as the integral type.
1027+ const ONE : Self ;
1028+ /// Value for zero as the integral type.
1029+ const ZERO : Self ;
1030+
1031+ /// Perform a checked left shift on the integral type.
1032+ fn checked_shl ( self , rhs : u32 ) -> Option < Self > ;
1033+ /// Perform a checked right shift on the integral type.
1034+ fn checked_shr ( self , rhs : u32 ) -> Option < Self > ;
1035+ }
1036+
1037+ impl FiniteBitSetTy for u64 {
1038+ const DOMAIN_SIZE : u32 = 64 ;
1039+
1040+ const FILLED : Self = Self :: MAX ;
1041+ const EMPTY : Self = Self :: MIN ;
1042+
1043+ const ONE : Self = 1u64 ;
1044+ const ZERO : Self = 0u64 ;
1045+
1046+ fn checked_shl ( self , rhs : u32 ) -> Option < Self > {
1047+ self . checked_shl ( rhs)
1048+ }
1049+
1050+ fn checked_shr ( self , rhs : u32 ) -> Option < Self > {
1051+ self . checked_shr ( rhs)
1052+ }
1053+ }
1054+
1055+ impl std:: fmt:: Debug for FiniteBitSet < u64 > {
1056+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1057+ write ! ( f, "{:064b}" , self . 0 )
1058+ }
1059+ }
1060+
1061+ impl FiniteBitSetTy for u128 {
1062+ const DOMAIN_SIZE : u32 = 128 ;
1063+
1064+ const FILLED : Self = Self :: MAX ;
1065+ const EMPTY : Self = Self :: MIN ;
1066+
1067+ const ONE : Self = 1u128 ;
1068+ const ZERO : Self = 0u128 ;
1069+
1070+ fn checked_shl ( self , rhs : u32 ) -> Option < Self > {
1071+ self . checked_shl ( rhs)
1072+ }
1073+
1074+ fn checked_shr ( self , rhs : u32 ) -> Option < Self > {
1075+ self . checked_shr ( rhs)
1076+ }
1077+ }
1078+
1079+ impl std:: fmt:: Debug for FiniteBitSet < u128 > {
1080+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1081+ write ! ( f, "{:0128b}" , self . 0 )
1082+ }
1083+ }
1084+
1085+ /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range
1086+ /// representable by `T` are considered set.
1087+ #[ derive( Copy , Clone , Eq , PartialEq , RustcDecodable , RustcEncodable ) ]
1088+ pub struct FiniteBitSet < T : FiniteBitSetTy > ( pub T ) ;
1089+
1090+ impl < T : FiniteBitSetTy > FiniteBitSet < T > {
1091+ /// Creates a new, empty bitset.
1092+ pub fn new_empty ( ) -> Self {
1093+ Self ( T :: EMPTY )
1094+ }
1095+
1096+ /// Sets the `index`th bit.
1097+ pub fn set ( & mut self , index : u32 ) {
1098+ self . 0 |= T :: ONE . checked_shl ( index) . unwrap_or ( T :: ZERO ) ;
1099+ }
1100+
1101+ /// Unsets the `index`th bit.
1102+ pub fn clear ( & mut self , index : u32 ) {
1103+ self . 0 &= !T :: ONE . checked_shl ( index) . unwrap_or ( T :: ZERO ) ;
1104+ }
1105+
1106+ /// Sets the `i`th to `j`th bits.
1107+ pub fn set_range ( & mut self , range : Range < u32 > ) {
1108+ let bits = T :: FILLED
1109+ . checked_shl ( range. end - range. start )
1110+ . unwrap_or ( T :: ZERO )
1111+ . not ( )
1112+ . checked_shl ( range. start )
1113+ . unwrap_or ( T :: ZERO ) ;
1114+ self . 0 |= bits;
1115+ }
1116+
1117+ /// Is the set empty?
1118+ pub fn is_empty ( & self ) -> bool {
1119+ self . 0 == T :: EMPTY
1120+ }
1121+
1122+ /// Returns the domain size of the bitset.
1123+ pub fn within_domain ( & self , index : u32 ) -> bool {
1124+ index < T :: DOMAIN_SIZE
1125+ }
1126+
1127+ /// Returns if the `index`th bit is set.
1128+ pub fn contains ( & self , index : u32 ) -> Option < bool > {
1129+ self . within_domain ( index)
1130+ . then ( || ( ( self . 0 . checked_shr ( index) . unwrap_or ( T :: ONE ) ) & T :: ONE ) == T :: ONE )
1131+ }
1132+ }
1133+
1134+ impl < T : FiniteBitSetTy > Default for FiniteBitSet < T > {
1135+ fn default ( ) -> Self {
1136+ Self :: new_empty ( )
1137+ }
1138+ }
0 commit comments