@@ -41,9 +41,8 @@ pub type Word = c_ulong;
4141/// This is a sealed trait with no interface. It is implemented for types in this library that
4242/// `evdev` reports to userspace using bitfields.
4343pub trait BitValue : Copy + sealed:: BitValueImpl {
44- /// The largest value that can be stored in a [`BitSet`].
45- ///
46- /// Attempting to insert a value above this into a [`BitSet`] will panic.
44+ /// The largest value that can be stored in a [`BitSet`], after rounding to the next
45+ /// `unsigned long`.
4746 ///
4847 /// Note that the exact value used for this associated constant should not be relied on as it
4948 /// is not stable.
@@ -85,7 +84,9 @@ impl<V: BitValue> BitSet<V> {
8584 ///
8685 /// The number of [`Word`]s that make up any given [`BitSet`] can also vary between platforms,
8786 /// and is generally only guaranteed to be large enough to store
88- /// [`<V as BitValue>::MAX`][BitValue::MAX], but may be arbitrarily larger.
87+ /// [`<V as BitValue>::MAX`][BitValue::MAX], but will be rounded up to the next multiple of
88+ /// `sizeof(unsigned long)`.
89+ ///
8990 /// Additionally, the number of [`Word`]s may increase in minor and patch releases to make room
9091 /// for newly added enumeration constants.
9192 pub fn words ( & self ) -> & [ Word ] {
@@ -94,10 +95,6 @@ impl<V: BitValue> BitSet<V> {
9495
9596 /// Returns a mutable reference to the underlying [`Word`]s making up this [`BitSet`].
9697 ///
97- /// You should not set any bits to 1 whose indices are larger than
98- /// [`<V as BitValue>::MAX`][BitValue::MAX]. Doing so might cause the [`BitSet`] to behave
99- /// incorrectly.
100- ///
10198 /// Further, all the same considerations from [`BitSet::words`] apply here as well.
10299 pub fn words_mut ( & mut self ) -> & mut [ Word ] {
103100 self . words . as_mut ( )
@@ -119,16 +116,17 @@ impl<V: BitValue> BitSet<V> {
119116
120117 /// Returns whether `self` contains `value`.
121118 pub fn contains ( & self , value : V ) -> bool {
122- if value. into_index ( ) > V :: MAX . into_index ( ) {
123- return false ;
124- }
125119 let index = value. into_index ( ) ;
126120 let wordpos = index / Word :: BITS as usize ;
127121 let bitpos = index % Word :: BITS as usize ;
128122
129- let word = self . words . as_ref ( ) [ wordpos] ;
130- let bit = word & ( 1 << bitpos) != 0 ;
131- bit
123+ match self . words . as_ref ( ) . get ( wordpos) {
124+ Some ( & word) => {
125+ let bit = word & ( 1 << bitpos) != 0 ;
126+ bit
127+ }
128+ None => false ,
129+ }
132130 }
133131
134132 /// Inserts `value` into `self`, setting the appropriate bit.
@@ -137,38 +135,42 @@ impl<V: BitValue> BitSet<V> {
137135 ///
138136 /// # Panics
139137 ///
140- /// Panics if `value` is larger than [`<V as BitValue>::MAX`][BitValue::MAX].
138+ /// Panics if `value` is out of range and there is no bit allocated to store it.
139+ /// The total number of bits available is [`<V as BitValue>::MAX`][BitValue::MAX], rounded up to
140+ /// the nearest multiple of `sizeof(unsigned long)`.
141141 pub fn insert ( & mut self , value : V ) -> bool {
142- assert ! (
143- value. into_index( ) <= V :: MAX . into_index( ) ,
144- "value out of range for `BitSet` storage (value's index is {}, max is {})" ,
145- value. into_index( ) ,
146- V :: MAX . into_index( ) ,
147- ) ;
148-
149- let present = self . contains ( value) ;
150-
151142 let index = value. into_index ( ) ;
152143 let wordpos = index / Word :: BITS as usize ;
153144 let bitpos = index % Word :: BITS as usize ;
154- self . words . as_mut ( ) [ wordpos] |= 1 << bitpos;
155- present
145+ match self . words . as_mut ( ) . get_mut ( wordpos) {
146+ Some ( word) => {
147+ let old = * word;
148+ * word |= 1 << bitpos;
149+ * word != old
150+ }
151+ None => panic ! (
152+ "value out of range for `BitSet`: value's index is {index}, capacity is {}" ,
153+ size_of:: <Word >( ) * self . words( ) . len( ) ,
154+ ) ,
155+ }
156156 }
157157
158158 /// Removes `value` from the set.
159159 ///
160160 /// Returns `true` if it was present and has been removed, or `false` if it was not present.
161161 pub fn remove ( & mut self , value : V ) -> bool {
162- if value. into_index ( ) > V :: MAX . into_index ( ) {
163- return false ;
164- }
165162 let present = self . contains ( value) ;
166163
167164 let index = value. into_index ( ) ;
168165 let wordpos = index / Word :: BITS as usize ;
169166 let bitpos = index % Word :: BITS as usize ;
170- self . words . as_mut ( ) [ wordpos] &= !( 1 << bitpos) ;
171- present
167+ match self . words . as_mut ( ) . get_mut ( wordpos) {
168+ Some ( word) => {
169+ * word &= !( 1 << bitpos) ;
170+ present
171+ }
172+ None => false ,
173+ }
172174 }
173175
174176 /// Returns an iterator over all values in `self`.
@@ -338,7 +340,7 @@ mod tests {
338340 #[ test]
339341 fn bit0 ( ) {
340342 let mut set = BitSet :: new ( ) ;
341- set. insert ( InputProp ( 0 ) ) ;
343+ assert ! ( set. insert( InputProp ( 0 ) ) ) ;
342344
343345 assert ! ( set. contains( InputProp :: POINTER ) ) ;
344346 assert ! ( !set. contains( InputProp :: DIRECT ) ) ;
@@ -352,20 +354,34 @@ mod tests {
352354 #[ test]
353355 fn max ( ) {
354356 let mut set = BitSet :: new ( ) ;
355- set. insert ( InputProp :: MAX ) ;
357+ assert ! ( set. insert( InputProp :: MAX ) ) ;
356358
357359 assert ! ( !set. contains( InputProp :: POINTER ) ) ;
358360 assert ! ( !set. contains( InputProp :: DIRECT ) ) ;
359361 assert ! ( set. contains( InputProp :: MAX ) ) ;
360362 assert ! ( !set. contains( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
361363 assert ! ( !set. remove( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
364+
365+ assert ! ( set. insert( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
366+
367+ assert_eq ! (
368+ set. iter( ) . collect:: <Vec <_>>( ) ,
369+ & [ InputProp :: MAX , InputProp ( InputProp :: MAX . 0 + 1 ) ] ,
370+ ) ;
371+
372+ assert ! ( !set. contains( InputProp :: DIRECT ) ) ;
373+ assert ! ( set. contains( InputProp :: MAX ) ) ;
374+ assert ! ( set. contains( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
375+ assert ! ( set. remove( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
376+ assert ! ( set. contains( InputProp :: MAX ) ) ;
377+ assert ! ( !set. contains( InputProp ( InputProp :: MAX . 0 + 1 ) ) ) ;
362378 }
363379
364380 #[ test]
365381 #[ should_panic = "value out of range for `BitSet`" ]
366- fn above_max ( ) {
382+ fn out_of_range ( ) {
367383 let mut set = BitSet :: new ( ) ;
368- set. insert ( Abs :: from_raw ( Abs :: MAX . raw ( ) + 1 ) ) ;
384+ set. insert ( InputProp ( 200 ) ) ;
369385 }
370386
371387 #[ test]
0 commit comments