@@ -4,6 +4,7 @@ use std::fmt;
4
4
use std:: iter;
5
5
use std:: marker:: PhantomData ;
6
6
use std:: mem;
7
+ use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Not , Range , Shl } ;
7
8
use std:: slice;
8
9
9
10
#[ cfg( test) ]
@@ -1001,3 +1002,137 @@ fn word_index_and_mask<T: Idx>(elem: T) -> (usize, Word) {
1001
1002
let mask = 1 << ( elem % WORD_BITS ) ;
1002
1003
( word_index, mask)
1003
1004
}
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