Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ where R: BitRegister
}

/// Wraps a counter value as an assumed-good index into an `R` register.
///
/// For a safe alternative and additional documentation, see [`Self::new()`].
///
/// ## Parameters
///
Expand Down Expand Up @@ -643,6 +645,8 @@ where R: BitRegister
/// Wraps a counter value as an assumed-good position within an `R`
/// register.
///
/// For a safe alternative and additional documentation, see [`Self::new()`].
///
/// ## Parameters
///
/// - `value`: The counter value to mark as a position. This must be in the
Expand Down Expand Up @@ -768,6 +772,8 @@ where R: BitRegister

/// Wraps a selector value as an assumed-good selection in an `R` register.
///
/// For a safe alternative and additional documentation, see [`Self::new()`].
///
/// ## Parameters
///
/// - `sel`: A one-hot selection mask of a bit in an `R` register.
Expand Down
2 changes: 2 additions & 0 deletions src/ptr/single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ where

/// Constructs a `BitPtr` from an address and head index, without checking
/// the address for validity.
///
/// For a safe alternative and additional documentation, see [`Self::new()`].
///
/// ## Parameters
///
Expand Down
100 changes: 96 additions & 4 deletions src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ where
///
/// If `slice` is too long to encode into a `&BitSlice`, then the produced
/// bit-slice’s length is unspecified.
///
/// For a safe alternative and additional documentation, see [`Self::from_slice()`].
///
/// ## Safety
///
Expand All @@ -412,6 +414,8 @@ where
/// If `slice` is too long to encode into a `&mut BitSlice`, then the
/// produced bit-slice’s length is unspecified.
///
/// For a safe alternative and additional documentation, see [`Self::from_slice_mut()`].
///
/// ## Safety
///
/// You must ensure that `slice.len() < BitSlice::MAX_ELTS`.
Expand Down Expand Up @@ -756,6 +760,8 @@ where

/// Writes a new value into a single bit, without bounds checking.
///
/// For a safe alternative and additional documentation, see [`.set()`].
///
/// ## Parameters
///
/// - `&mut self`
Expand Down Expand Up @@ -811,6 +817,8 @@ where

/// Writes a new value into a bit, returning the previous value, without
/// bounds checking.
///
/// For a safe alternative and additional documentation, see [`.replace()`].
///
/// ## Safety
///
Expand Down Expand Up @@ -840,7 +848,7 @@ where

/// Swaps two bits in a bit-slice, without bounds checking.
///
/// See [`.swap()`] for documentation.
/// For a safe alternative and additional documentation, see [`.swap()`].
///
/// ## Safety
///
Expand All @@ -861,8 +869,8 @@ where

/// Splits a bit-slice at an index, without bounds checking.
///
/// See [`.split_at()`] for documentation.
///
/// For a safe alternative and additional documentation, see [`.split_at()`].
///
/// ## Safety
///
/// You must ensure that `mid` is in the range `0 ..= self.len()`.
Expand All @@ -887,7 +895,7 @@ where

/// Splits a mutable bit-slice at an index, without bounds checking.
///
/// See [`.split_at_mut()`] for documentation.
/// For a safe alternative and additional documentation, see [`.split_at()`].
///
/// ## Safety
///
Expand Down Expand Up @@ -917,6 +925,8 @@ where
/// itself, without doing bounds checks.
///
/// The regions are allowed to overlap.
///
/// For a safe alternative and additional documentation, see [`.copy_within()`].
///
/// ## Parameters
///
Expand Down Expand Up @@ -1701,6 +1711,8 @@ where
/// require an `&mut` reference, and allows bit-slices with alias-safe
/// storage to share write permissions.
///
/// For a safe alternative and additional documentation, see [`.set_aliased()`].
///
/// ## Parameters
///
/// - `&self`: This method only exists on bit-slices with alias-safe
Expand Down Expand Up @@ -1731,6 +1743,86 @@ where
pub unsafe fn set_aliased_unchecked(&self, index: usize, value: bool) {
self.as_bitptr().add(index).freeze().frozen_write_bit(value);
}

/// Replaces the value of a single bit, using alias-safe operations,
/// returning the previous value.
///
/// This is equivalent to [`.replace()`], except that it does not require an
/// `&mut` reference, and allows bit-slices with alias-safe storage to share
/// write permissions.
///
/// ## Parameters
///
/// - `&self`: This method only exists on bit-slices with alias-safe
/// storage, and so does not require exclusive access.
/// - `index`: The bit index to set. It must be in `0 .. self.len()`.
/// - `value`: The new bit-value to write into the bit at `index`.
///
/// ## Panics
///
/// This panics if `index` is out of bounds.
///
/// ## Examples
///
/// ```rust
/// use bitvec::prelude::*;
/// use core::cell::Cell;
///
/// let bits: &BitSlice<_, _> = bits![Cell<usize>, Lsb0; 0, 1];
/// assert!(!bits.replace_aliased(0, true));
/// assert!(bits.replace_aliased(1, false));
///
/// assert_eq!(bits, bits![1, 0]);
/// ```
///
/// [`.replace()`]: Self::replace
#[inline]
pub fn replace_aliased(&self, index: usize, value: bool) -> bool {
self.assert_in_bounds(index, 0..self.len());
unsafe { self.replace_aliased_unchecked(index, value) }
}

/// Replaces the value of a single bit, using alias-safe operations and
/// without bounds checking, returning the previous value.
///
/// This is equivalent to [`.replace_unchecked()`], except that it does not
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You link to fn replace_unchecked, but you do not link to fn replace_aliased. Please do that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Peter, would you mind briefly elaborating on what you mean exactly, or providing a code suggestion? I couldn't find any equivalent cross linking from .replace_unchecked() to .replace() to follow suit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have, regardless of what existing docs say:

This is for standard slice:

"For a safe alternative see get."

Screenshot_20260418_133151_Brave.jpg

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vincent, you may update set_aliased_unchecked and replace_unchecked as well

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated all unsafe _unchecked methods I could find, accordingly.

/// require an `&mut` reference, and allows bit-slices with alias-safe
/// storage to share write permissions.
///
/// For a safe alternative and additional documentation, see [`.replace_aliased()`].
///
/// ## Parameters
///
/// - `&self`: This method only exists on bit-slices with alias-safe
/// storage, and so does not require exclusive access.
/// - `index`: The bit index to replace. It must be in `0 .. self.len()`.
/// - `value`: The new bit-value to write into the bit at `index`.
///
/// ## Safety
///
/// The caller must ensure that `index` is not out of bounds.
///
/// ## Examples
///
/// ```rust
/// use bitvec::prelude::*;
/// use core::cell::Cell;
///
/// let data = Cell::new(0u8);
/// let bits = &data.view_bits::<Lsb0>()[.. 2];
/// assert!(!unsafe { bits.replace_aliased_unchecked(3, true) });
/// assert_eq!(data.get(), 8);
/// ```
///
/// [`.replace_unchecked()`]: Self::replace_unchecked
#[inline]
pub unsafe fn replace_aliased_unchecked(
&self,
index: usize,
value: bool,
) -> bool {
self.as_bitptr().add(index).freeze().frozen_write_bit(value)
}
}

/// Miscellaneous information.
Expand Down
4 changes: 4 additions & 0 deletions src/slice/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ where
///
/// This has the same arguments and behavior as [`.get()`], except that it
/// does not check that `index` is in bounds.
///
/// For a safe alternative and additional documentation, see [`.get()`].
///
/// ## Original
///
Expand Down Expand Up @@ -488,6 +490,8 @@ where
/// This has the same arguments and behavior as [`.get_mut()`], except that
/// it does not check that `index` is in bounds.
///
/// For a safe alternative and additional documentation, see [`.get_mut()`].
///
/// ## Original
///
/// [`slice::get_unchecked_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked_mut)
Expand Down
6 changes: 6 additions & 0 deletions src/slice/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ fn aliasing() {
assert!(bits[0]);
b.set_aliased(0, false);
assert!(!bits[0]);

let (a, b) = (bits, bits);
assert!(!a.replace_aliased(0, true));
assert!(bits[0]);
assert!(b.replace_aliased(0, false));
assert!(!bits[0]);
}

#[test]
Expand Down