Skip to content

Commit 5fc93bf

Browse files
authored
Document unsafe blocks (#91)
1 parent 460bccc commit 5fc93bf

1 file changed

Lines changed: 33 additions & 29 deletions

File tree

src/lib.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//!
1414
#![doc(html_root_url = "https://docs.rs/fixedbitset/0.4.2/")]
1515
#![cfg_attr(not(feature = "std"), no_std)]
16+
#![forbid(clippy::undocumented_unsafe_blocks)]
1617

1718
#[cfg(not(feature = "std"))]
1819
extern crate alloc;
@@ -105,9 +106,9 @@ impl FixedBitSet {
105106
// Disable bits in blocks beyond capacity
106107
let end = data.len() * BITS;
107108
for (block, mask) in Masks::new(bits..end, end) {
108-
unsafe {
109-
*data.get_unchecked_mut(block) &= !mask;
110-
}
109+
// SAFETY: Masks cannot return a block index that is out of range.
110+
let block = unsafe { data.get_unchecked_mut(block) };
111+
*block &= !mask;
111112
}
112113
FixedBitSet { data, length: bits }
113114
}
@@ -195,7 +196,7 @@ impl FixedBitSet {
195196
/// Clear all bits.
196197
#[inline]
197198
pub fn clear(&mut self) {
198-
for elt in &mut self.data[..] {
199+
for elt in &mut self.data {
199200
*elt = 0
200201
}
201202
}
@@ -212,6 +213,7 @@ impl FixedBitSet {
212213
self.length
213214
);
214215
let (block, i) = div_rem(bit);
216+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
215217
unsafe {
216218
*self.data.get_unchecked_mut(block) |= 1 << i;
217219
}
@@ -229,6 +231,7 @@ impl FixedBitSet {
229231
self.length
230232
);
231233
let (block, i) = div_rem(bit);
234+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
232235
unsafe {
233236
*self.data.get_unchecked_mut(block) &= !(1 << i);
234237
}
@@ -246,6 +249,7 @@ impl FixedBitSet {
246249
self.length
247250
);
248251
let (block, i) = div_rem(bit);
252+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
249253
unsafe {
250254
let word = self.data.get_unchecked_mut(block);
251255
let prev = *word & (1 << i) != 0;
@@ -266,6 +270,7 @@ impl FixedBitSet {
266270
self.length
267271
);
268272
let (block, i) = div_rem(bit);
273+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
269274
unsafe {
270275
*self.data.get_unchecked_mut(block) ^= 1 << i;
271276
}
@@ -281,13 +286,12 @@ impl FixedBitSet {
281286
self.length
282287
);
283288
let (block, i) = div_rem(bit);
284-
unsafe {
285-
let elt = self.data.get_unchecked_mut(block);
286-
if enabled {
287-
*elt |= 1 << i;
288-
} else {
289-
*elt &= !(1 << i);
290-
}
289+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
290+
let elt = unsafe { self.data.get_unchecked_mut(block) };
291+
if enabled {
292+
*elt |= 1 << i;
293+
} else {
294+
*elt &= !(1 << i);
291295
}
292296
}
293297

@@ -304,13 +308,12 @@ impl FixedBitSet {
304308
);
305309
let (to_block, t) = div_rem(to);
306310
let enabled = self.contains(from);
307-
unsafe {
308-
let to_elt = self.data.get_unchecked_mut(to_block);
309-
if enabled {
310-
*to_elt |= 1 << t;
311-
} else {
312-
*to_elt &= !(1 << t);
313-
}
311+
// SAFETY: The above assertion ensures that the block is inside the Vec's allocation.
312+
let to_elt = unsafe { self.data.get_unchecked_mut(to_block) };
313+
if enabled {
314+
*to_elt |= 1 << t;
315+
} else {
316+
*to_elt &= !(1 << t);
314317
}
315318
}
316319

@@ -322,8 +325,9 @@ impl FixedBitSet {
322325
#[inline]
323326
pub fn count_ones<T: IndexRange>(&self, range: T) -> usize {
324327
Masks::new(range, self.length)
325-
.map(|(block, mask)| unsafe {
326-
let value = *self.data.get_unchecked(block);
328+
.map(|(block, mask)| {
329+
// SAFETY: Masks cannot return a block index that is out of range.
330+
let value = unsafe { *self.data.get_unchecked(block) };
327331
(value & mask).count_ones() as usize
328332
})
329333
.sum()
@@ -337,12 +341,12 @@ impl FixedBitSet {
337341
#[inline]
338342
pub fn set_range<T: IndexRange>(&mut self, range: T, enabled: bool) {
339343
for (block, mask) in Masks::new(range, self.length) {
340-
unsafe {
341-
if enabled {
342-
*self.data.get_unchecked_mut(block) |= mask;
343-
} else {
344-
*self.data.get_unchecked_mut(block) &= !mask;
345-
}
344+
// SAFETY: Masks cannot return a block index that is out of range.
345+
let block = unsafe { self.data.get_unchecked_mut(block) };
346+
if enabled {
347+
*block |= mask;
348+
} else {
349+
*block &= !mask;
346350
}
347351
}
348352
}
@@ -365,9 +369,9 @@ impl FixedBitSet {
365369
#[inline]
366370
pub fn toggle_range<T: IndexRange>(&mut self, range: T) {
367371
for (block, mask) in Masks::new(range, self.length) {
368-
unsafe {
369-
*self.data.get_unchecked_mut(block) ^= mask;
370-
}
372+
// SAFETY: Masks cannot return a block index that is out of range.
373+
let block = unsafe { self.data.get_unchecked_mut(block) };
374+
*block ^= mask;
371375
}
372376
}
373377

0 commit comments

Comments
 (0)