1
1
// Copyright 2019-2022 ChainSafe Systems
2
2
// SPDX-License-Identifier: Apache-2.0, MIT
3
3
4
+ // disable this lint because it can actually cause performance regressions, and usually leads to
5
+ // hard to read code.
6
+ #![ allow( clippy:: comparison_chain) ]
7
+
4
8
pub mod iter;
5
9
mod range;
6
10
mod rleplus;
7
11
mod unvalidated;
8
12
9
13
use std:: collections:: BTreeSet ;
10
- use std:: iter:: FromIterator ;
11
14
use std:: ops:: {
12
15
BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Range , Sub , SubAssign ,
13
16
} ;
14
17
15
18
use iter:: { ranges_from_bits, RangeIterator } ;
16
19
pub ( crate ) use range:: RangeSize ;
20
+ pub use rleplus:: Error ;
21
+ use thiserror:: Error ;
17
22
pub use unvalidated:: { UnvalidatedBitField , Validate } ;
18
23
19
- type Result < T > = std:: result:: Result < T , & ' static str > ;
24
+ #[ derive( Clone , Error , Debug ) ]
25
+ #[ error( "bitfields may not include u64::MAX" ) ]
26
+ pub struct OutOfRangeError ;
27
+
28
+ impl From < OutOfRangeError > for Error {
29
+ fn from ( _: OutOfRangeError ) -> Self {
30
+ Error :: RLEOverflow
31
+ }
32
+ }
20
33
21
34
/// A bit field with buffered insertion/removal that serializes to/from RLE+. Similar to
22
35
/// `HashSet<u64>`, but more memory-efficient when long runs of 1s and 0s are present.
@@ -36,22 +49,79 @@ impl PartialEq for BitField {
36
49
}
37
50
}
38
51
39
- impl FromIterator < u64 > for BitField {
40
- fn from_iter < I : IntoIterator < Item = u64 > > ( iter : I ) -> Self {
41
- let mut vec: Vec < _ > = iter. into_iter ( ) . collect ( ) ;
42
- if vec. is_empty ( ) {
43
- Self :: new ( )
52
+ /// Possibly a valid bitfield, or an out of bounds error. Ideally we'd just use a result, but we
53
+ /// can't implement [`FromIterator`] on a [`Result`] due to coherence.
54
+ ///
55
+ /// You probably want to call [`BitField::try_from_bits`] instead of using this directly.
56
+ #[ doc( hidden) ]
57
+ pub enum MaybeBitField {
58
+ /// A valid bitfield.
59
+ Ok ( BitField ) ,
60
+ /// Out of bounds.
61
+ OutOfBounds ,
62
+ }
63
+
64
+ impl MaybeBitField {
65
+ pub fn unwrap ( self ) -> BitField {
66
+ use MaybeBitField :: * ;
67
+ match self {
68
+ Ok ( bf) => bf,
69
+ OutOfBounds => panic ! ( "bitfield bit out of bounds" ) ,
70
+ }
71
+ }
72
+
73
+ pub fn expect ( self , message : & str ) -> BitField {
74
+ use MaybeBitField :: * ;
75
+ match self {
76
+ Ok ( bf) => bf,
77
+ OutOfBounds => panic ! ( "{}" , message) ,
78
+ }
79
+ }
80
+ }
81
+
82
+ impl TryFrom < MaybeBitField > for BitField {
83
+ type Error = OutOfRangeError ;
84
+
85
+ fn try_from ( value : MaybeBitField ) -> Result < Self , Self :: Error > {
86
+ match value {
87
+ MaybeBitField :: Ok ( bf) => Ok ( bf) ,
88
+ MaybeBitField :: OutOfBounds => Err ( OutOfRangeError ) ,
89
+ }
90
+ }
91
+ }
92
+
93
+ impl FromIterator < bool > for MaybeBitField {
94
+ fn from_iter < T : IntoIterator < Item = bool > > ( iter : T ) -> MaybeBitField {
95
+ let mut iter = iter. into_iter ( ) . fuse ( ) ;
96
+ let bits = ( 0u64 ..u64:: MAX )
97
+ . zip ( & mut iter)
98
+ . filter ( |& ( _, b) | b)
99
+ . map ( |( i, _) | i) ;
100
+ let bf = BitField :: from_ranges ( ranges_from_bits ( bits) ) ;
101
+
102
+ // Now, if we have remaining bits, raise an error. Otherwise, we're good.
103
+ if iter. next ( ) . is_some ( ) {
104
+ MaybeBitField :: OutOfBounds
44
105
} else {
45
- vec. sort_unstable ( ) ;
46
- Self :: from_ranges ( ranges_from_bits ( vec) )
106
+ MaybeBitField :: Ok ( bf)
47
107
}
48
108
}
49
109
}
50
110
51
- impl FromIterator < bool > for BitField {
52
- fn from_iter < I : IntoIterator < Item = bool > > ( iter : I ) -> Self {
53
- let bits = ( 0u64 ..) . zip ( iter) . filter ( |& ( _, b) | b) . map ( |( i, _) | i) ;
54
- Self :: from_ranges ( ranges_from_bits ( bits) )
111
+ impl FromIterator < u64 > for MaybeBitField {
112
+ fn from_iter < T : IntoIterator < Item = u64 > > ( iter : T ) -> MaybeBitField {
113
+ let mut vec: Vec < _ > = iter. into_iter ( ) . collect ( ) ;
114
+ if vec. is_empty ( ) {
115
+ MaybeBitField :: Ok ( BitField :: new ( ) )
116
+ } else {
117
+ vec. sort_unstable ( ) ;
118
+ vec. dedup ( ) ;
119
+ if vec. last ( ) == Some ( & u64:: MAX ) {
120
+ MaybeBitField :: OutOfBounds
121
+ } else {
122
+ MaybeBitField :: Ok ( BitField :: from_ranges ( ranges_from_bits ( vec) ) )
123
+ }
124
+ }
55
125
}
56
126
}
57
127
@@ -69,10 +139,33 @@ impl BitField {
69
139
}
70
140
}
71
141
72
- /// Adds the bit at a given index to the bit field.
142
+ /// Tries to create a new bitfield from a bit iterator. It fails if the resulting bitfield would
143
+ /// contain values not in the range `0..u64::MAX` (non-inclusive).
144
+ pub fn try_from_bits < I > ( iter : I ) -> Result < Self , OutOfRangeError >
145
+ where
146
+ I : IntoIterator ,
147
+ MaybeBitField : FromIterator < I :: Item > ,
148
+ {
149
+ iter. into_iter ( ) . collect :: < MaybeBitField > ( ) . try_into ( )
150
+ }
151
+
152
+ /// Adds the bit at a given index to the bit field, panicing if it's out of range.
153
+ ///
154
+ /// # Panics
155
+ ///
156
+ /// Panics if `bit` is `u64::MAX`.
73
157
pub fn set ( & mut self , bit : u64 ) {
158
+ self . try_set ( bit) . unwrap ( )
159
+ }
160
+
161
+ /// Adds the bit at a given index to the bit field, returning an error if it's out of range.
162
+ pub fn try_set ( & mut self , bit : u64 ) -> Result < ( ) , OutOfRangeError > {
163
+ if bit == u64:: MAX {
164
+ return Err ( OutOfRangeError ) ;
165
+ }
74
166
self . unset . remove ( & bit) ;
75
167
self . set . insert ( bit) ;
168
+ Ok ( ( ) )
76
169
}
77
170
78
171
/// Removes the bit at a given index from the bit field.
@@ -114,8 +207,7 @@ impl BitField {
114
207
self . set . iter ( ) . min ( ) . copied ( ) ,
115
208
self . ranges
116
209
. iter ( )
117
- . filter_map ( |r| r. clone ( ) . find ( |i| !self . unset . contains ( i) ) )
118
- . next ( ) ,
210
+ . find_map ( |r| r. clone ( ) . find ( |i| !self . unset . contains ( i) ) ) ,
119
211
) {
120
212
( None , None ) => None ,
121
213
( Some ( v) , None ) | ( None , Some ( v) ) => Some ( v) ,
@@ -165,12 +257,12 @@ impl BitField {
165
257
}
166
258
167
259
/// Returns an iterator over the indices of the bit field's set bits if the number
168
- /// of set bits in the bit field does not exceed `max`. Returns an error otherwise.
169
- pub fn bounded_iter ( & self , max : u64 ) -> Result < impl Iterator < Item = u64 > + ' _ > {
260
+ /// of set bits in the bit field does not exceed `max`. Returns `None` otherwise.
261
+ pub fn bounded_iter ( & self , max : u64 ) -> Option < impl Iterator < Item = u64 > + ' _ > {
170
262
if self . len ( ) <= max {
171
- Ok ( self . iter ( ) )
263
+ Some ( self . iter ( ) )
172
264
} else {
173
- Err ( "Bits set exceeds max in retrieval" )
265
+ None
174
266
}
175
267
}
176
268
@@ -197,15 +289,15 @@ impl BitField {
197
289
}
198
290
199
291
/// Returns a slice of the bit field with the start index of set bits
200
- /// and number of bits to include in the slice. Returns an error if the
201
- /// bit field contains fewer than `start + len` set bits.
202
- pub fn slice ( & self , start : u64 , len : u64 ) -> Result < Self > {
292
+ /// and number of bits to include in the slice. Returns `None` if the bit
293
+ /// field contains fewer than `start + len` set bits.
294
+ pub fn slice ( & self , start : u64 , len : u64 ) -> Option < Self > {
203
295
let slice = BitField :: from_ranges ( self . ranges ( ) . skip_bits ( start) . take_bits ( len) ) ;
204
296
205
297
if slice. len ( ) == len {
206
- Ok ( slice)
298
+ Some ( slice)
207
299
} else {
208
- Err ( "Not enough bits" )
300
+ None
209
301
}
210
302
}
211
303
@@ -330,7 +422,7 @@ macro_rules! bitfield {
330
422
std:: iter:: once( $head != 0_u32 ) . chain( bitfield!( @iter $( $tail) ,* ) )
331
423
} ;
332
424
( $( $val: literal) ,* $( , ) ?) => {
333
- bitfield!( @iter $( $val) ,* ) . collect:: <$crate:: BitField > ( )
425
+ bitfield!( @iter $( $val) ,* ) . collect:: <$crate:: MaybeBitField > ( ) . unwrap ( )
334
426
} ;
335
427
}
336
428
0 commit comments