Skip to content

Commit c6f976a

Browse files
authored
Unsafe *_unchecked variants for various point functions (#102)
1 parent 3e2cc8a commit c6f976a

File tree

1 file changed

+98
-13
lines changed

1 file changed

+98
-13
lines changed

src/lib.rs

+98-13
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,20 @@ impl FixedBitSet {
211211
}
212212
}
213213

214+
/// Return **true** if the bit is enabled in the **FixedBitSet**,
215+
/// **false** otherwise.
216+
///
217+
/// Note: unlike `contains`, calling this with an invalid `bit`
218+
/// is undefined behavior.
219+
///
220+
/// # Safety
221+
/// `bit` must be less than `self.len()`
222+
#[inline]
223+
pub unsafe fn contains_unchecked(&self, bit: usize) -> bool {
224+
let (block, i) = div_rem(bit);
225+
(self.data.get_unchecked(block) & (1 << i)) != 0
226+
}
227+
214228
/// Clear all bits.
215229
#[inline]
216230
pub fn clear(&mut self) {
@@ -226,10 +240,22 @@ impl FixedBitSet {
226240
pub fn insert(&mut self, bit: usize) {
227241
assert!(
228242
bit < self.length,
229-
"insert at index {} exceeds fixbitset size {}",
243+
"insert at index {} exceeds fixedbitset size {}",
230244
bit,
231245
self.length
232246
);
247+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
248+
unsafe {
249+
self.insert_unchecked(bit);
250+
}
251+
}
252+
253+
/// Enable `bit` without any length checks.
254+
///
255+
/// # Safety
256+
/// `bit` must be less than `self.len()`
257+
#[inline]
258+
pub unsafe fn insert_unchecked(&mut self, bit: usize) {
233259
let (block, i) = div_rem(bit);
234260
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
235261
unsafe {
@@ -244,10 +270,22 @@ impl FixedBitSet {
244270
pub fn remove(&mut self, bit: usize) {
245271
assert!(
246272
bit < self.length,
247-
"remove at index {} exceeds fixbitset size {}",
273+
"remove at index {} exceeds fixedbitset size {}",
248274
bit,
249275
self.length
250276
);
277+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
278+
unsafe {
279+
self.remove_unchecked(bit);
280+
}
281+
}
282+
283+
/// Disable `bit` without any bounds checking.
284+
///
285+
/// # Safety
286+
/// `bit` must be less than `self.len()`
287+
#[inline]
288+
pub unsafe fn remove_unchecked(&mut self, bit: usize) {
251289
let (block, i) = div_rem(bit);
252290
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
253291
unsafe {
@@ -262,10 +300,20 @@ impl FixedBitSet {
262300
pub fn put(&mut self, bit: usize) -> bool {
263301
assert!(
264302
bit < self.length,
265-
"put at index {} exceeds fixbitset size {}",
303+
"put at index {} exceeds fixedbitset size {}",
266304
bit,
267305
self.length
268306
);
307+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
308+
unsafe { self.put_unchecked(bit) }
309+
}
310+
311+
/// Enable `bit`, and return its previous value without doing any bounds checking.
312+
///
313+
/// # Safety
314+
/// `bit` must be less than `self.len()`
315+
#[inline]
316+
pub unsafe fn put_unchecked(&mut self, bit: usize) -> bool {
269317
let (block, i) = div_rem(bit);
270318
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
271319
unsafe {
@@ -283,26 +331,52 @@ impl FixedBitSet {
283331
pub fn toggle(&mut self, bit: usize) {
284332
assert!(
285333
bit < self.length,
286-
"toggle at index {} exceeds fixbitset size {}",
334+
"toggle at index {} exceeds fixedbitset size {}",
287335
bit,
288336
self.length
289337
);
338+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
339+
unsafe {
340+
self.toggle_unchecked(bit);
341+
}
342+
}
343+
344+
/// Toggle `bit` (inverting its state) without any bounds checking.
345+
///
346+
/// # Safety
347+
/// `bit` must be less than `self.len()`
348+
#[inline]
349+
pub unsafe fn toggle_unchecked(&mut self, bit: usize) {
290350
let (block, i) = div_rem(bit);
291351
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
292352
unsafe {
293353
*self.data.get_unchecked_mut(block) ^= 1 << i;
294354
}
295355
}
296356

357+
/// Sets a bit to the provided `enabled` value.
358+
///
297359
/// **Panics** if **bit** is out of bounds.
298360
#[inline]
299361
pub fn set(&mut self, bit: usize, enabled: bool) {
300362
assert!(
301363
bit < self.length,
302-
"set at index {} exceeds fixbitset size {}",
364+
"set at index {} exceeds fixedbitset size {}",
303365
bit,
304366
self.length
305367
);
368+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
369+
unsafe {
370+
self.set_unchecked(bit, enabled);
371+
}
372+
}
373+
374+
/// Sets a bit to the provided `enabled` value without doing any bounds checking.
375+
///
376+
/// # Safety
377+
/// `bit` must be less than `self.len()`
378+
#[inline]
379+
pub unsafe fn set_unchecked(&mut self, bit: usize, enabled: bool) {
306380
let (block, i) = div_rem(bit);
307381
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
308382
let elt = unsafe { self.data.get_unchecked_mut(block) };
@@ -315,24 +389,35 @@ impl FixedBitSet {
315389

316390
/// Copies boolean value from specified bit to the specified bit.
317391
///
392+
/// If `from` is out-of-bounds, `to` will be unset.
393+
///
318394
/// **Panics** if **to** is out of bounds.
319395
#[inline]
320396
pub fn copy_bit(&mut self, from: usize, to: usize) {
321397
assert!(
322398
to < self.length,
323-
"copy at index {} exceeds fixbitset size {}",
399+
"copy to index {} exceeds fixedbitset size {}",
324400
to,
325401
self.length
326402
);
327-
let (to_block, t) = div_rem(to);
328403
let enabled = self.contains(from);
329404
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
330-
let to_elt = unsafe { self.data.get_unchecked_mut(to_block) };
331-
if enabled {
332-
*to_elt |= 1 << t;
333-
} else {
334-
*to_elt &= !(1 << t);
335-
}
405+
unsafe { self.set_unchecked(to, enabled) };
406+
}
407+
408+
/// Copies boolean value from specified bit to the specified bit.
409+
///
410+
/// Note: unlike `copy_bit`, calling this with an invalid `from`
411+
/// is undefined behavior.
412+
///
413+
/// # Safety
414+
/// `to` must both be less than `self.len()`
415+
#[inline]
416+
pub unsafe fn copy_bit_unchecked(&mut self, from: usize, to: usize) {
417+
// SAFETY: Caller must ensure that `from` is within bounds.
418+
let enabled = self.contains_unchecked(from);
419+
// SAFETY: Caller must ensure that `to` is within bounds.
420+
self.set_unchecked(to, enabled);
336421
}
337422

338423
/// Count the number of set bits in the given bit range.

0 commit comments

Comments
 (0)