| #![doc = include_str!("../doc/slice.md")] |
| |
| #[cfg(feature = "alloc")] |
| use alloc::vec::Vec; |
| use core::{ |
| marker::PhantomData, |
| ops::RangeBounds, |
| }; |
| |
| use funty::Integral; |
| use tap::Pipe; |
| #[cfg(feature = "alloc")] |
| use tap::Tap; |
| use wyz::{ |
| bidi::BidiIterator, |
| comu::{ |
| Const, |
| Mut, |
| }, |
| range::RangeExt, |
| }; |
| |
| #[cfg(feature = "alloc")] |
| use crate::vec::BitVec; |
| use crate::{ |
| domain::{ |
| BitDomain, |
| Domain, |
| }, |
| mem, |
| order::{ |
| BitOrder, |
| Lsb0, |
| Msb0, |
| }, |
| ptr::{ |
| self as bv_ptr, |
| BitPtr, |
| BitPtrRange, |
| BitSpan, |
| BitSpanError, |
| }, |
| store::BitStore, |
| }; |
| |
| mod api; |
| mod iter; |
| mod ops; |
| mod specialization; |
| mod tests; |
| mod traits; |
| |
| pub use self::{ |
| api::*, |
| iter::*, |
| }; |
| |
| #[repr(transparent)] |
| #[doc = include_str!("../doc/slice/BitSlice.md")] |
| pub struct BitSlice<T = usize, O = Lsb0> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// The ordering of bits within a `T` register. |
| _ord: PhantomData<O>, |
| /// The register type used for storage. |
| _typ: PhantomData<[T]>, |
| /// Indicate that this is a newtype wrapper over a wholly-untyped slice. |
| /// |
| /// This is necessary in order for the Rust compiler to remove restrictions |
| /// on the possible values of reference handles to this type. Any other |
| /// slice type here (such as `[u8]` or `[T]`) would require that `&/mut |
| /// BitSlice` handles have values that correctly describe the region, and |
| /// the encoding *does not* do this. As such, reference handles to |
| /// `BitSlice` must not be even implicitly dereferenceäble to real memory, |
| /// and the slice must be a ZST. |
| /// |
| /// References to a ZST have no restrictions about what the values can be, |
| /// as they are never able to dereference real memory and thus both |
| /// addresses and lengths are meaningless to the memory inspector. |
| /// |
| /// See `ptr::span` for more information on the encoding scheme used in |
| /// references to `BitSlice`. |
| _mem: [()], |
| } |
| |
| /// Constructors. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Produces an empty bit-slice with an arbitrary lifetime. |
| /// |
| /// ## Original |
| /// |
| /// This is equivalent to the `&[]` literal. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(BitSlice::<u16, LocalBits>::empty().is_empty()); |
| /// assert_eq!(bits![], BitSlice::<u8, Msb0>::empty()); |
| /// ``` |
| #[inline] |
| pub fn empty<'a>() -> &'a Self { |
| unsafe { BitSpan::<Const, T, O>::EMPTY.into_bitslice_ref() } |
| } |
| |
| /// Produces an empty bit-slice with an arbitrary lifetime. |
| /// |
| /// ## Original |
| /// |
| /// This is equivalent to the `&mut []` literal. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(BitSlice::<u16, LocalBits>::empty_mut().is_empty()); |
| /// assert_eq!(bits![mut], BitSlice::<u8, Msb0>::empty_mut()); |
| /// ``` |
| #[inline] |
| pub fn empty_mut<'a>() -> &'a mut Self { |
| unsafe { BitSpan::<Mut, T, O>::EMPTY.into_bitslice_mut() } |
| } |
| |
| /// Constructs a shared `&BitSlice` reference over a shared element. |
| /// |
| /// The [`BitView`] trait, implemented on all [`BitStore`] implementors, |
| /// provides a [`.view_bits::<O>()`] method which delegates to this function |
| /// and may be more convenient for you to write. |
| /// |
| /// ## Parameters |
| /// |
| /// - `elem`: A shared reference to a memory element. |
| /// |
| /// ## Returns |
| /// |
| /// A shared `&BitSlice` over `elem`. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let elem = 0u8; |
| /// let bits = BitSlice::<_, Lsb0>::from_element(&elem); |
| /// assert_eq!(bits.len(), 8); |
| /// |
| /// let bits = elem.view_bits::<Lsb0>(); |
| /// ``` |
| /// |
| /// [`BitStore`]: crate::store::BitStore |
| /// [`BitView`]: crate::view::BitView |
| /// [`.view_bits::<O>()`]: crate::view::BitView::view_bits |
| #[inline] |
| pub fn from_element(elem: &T) -> &Self { |
| unsafe { |
| BitPtr::from_ref(elem) |
| .span_unchecked(mem::bits_of::<T::Mem>()) |
| .into_bitslice_ref() |
| } |
| } |
| |
| /// Constructs an exclusive `&mut BitSlice` reference over an element. |
| /// |
| /// The [`BitView`] trait, implemented on all [`BitStore`] implementors, |
| /// provides a [`.view_bits_mut::<O>()`] method which delegates to this |
| /// function and may be more convenient for you to write. |
| /// |
| /// ## Parameters |
| /// |
| /// - `elem`: An exclusive reference to a memory element. |
| /// |
| /// ## Returns |
| /// |
| /// An exclusive `&mut BitSlice` over `elem`. |
| /// |
| /// Note that the original `elem` reference will be inaccessible for the |
| /// duration of the returned bit-slice handle’s lifetime. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut elem = 0u8; |
| /// let bits = BitSlice::<_, Lsb0>::from_element_mut(&mut elem); |
| /// bits.set(1, true); |
| /// assert!(bits[1]); |
| /// assert_eq!(elem, 2); |
| /// |
| /// let bits = elem.view_bits_mut::<Lsb0>(); |
| /// ``` |
| /// |
| /// [`BitStore`]: crate::store::BitStore |
| /// [`BitView`]: crate::view::BitView |
| /// [`.view_bits_mut::<O>()`]: crate::view::BitView::view_bits_mut |
| #[inline] |
| pub fn from_element_mut(elem: &mut T) -> &mut Self { |
| unsafe { |
| BitPtr::from_mut(elem) |
| .span_unchecked(mem::bits_of::<T::Mem>()) |
| .into_bitslice_mut() |
| } |
| } |
| |
| /// Constructs a shared `&BitSlice` reference over a slice of elements. |
| /// |
| /// The [`BitView`] trait, implemented on all `[T]` slices, provides a |
| /// [`.view_bits::<O>()`] method which delegates to this function and may be |
| /// more convenient for you to write. |
| /// |
| /// ## Parameters |
| /// |
| /// - `slice`: A shared reference to a slice of memory elements. |
| /// |
| /// ## Returns |
| /// |
| /// A shared `BitSlice` reference over all of `slice`. |
| /// |
| /// ## Panics |
| /// |
| /// This will panic if `slice` is too long to encode as a bit-slice view. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let data = [0u16, 1]; |
| /// let bits = BitSlice::<_, Lsb0>::from_slice(&data); |
| /// assert!(bits[16]); |
| /// |
| /// let bits = data.view_bits::<Lsb0>(); |
| /// ``` |
| /// |
| /// [`BitView`]: crate::view::BitView |
| /// [`.view_bits::<O>()`]: crate::view::BitView::view_bits |
| #[inline] |
| pub fn from_slice(slice: &[T]) -> &Self { |
| Self::try_from_slice(slice).unwrap() |
| } |
| |
| /// Attempts to construct a shared `&BitSlice` reference over a slice of |
| /// elements. |
| /// |
| /// The [`BitView`], implemented on all `[T]` slices, provides a |
| /// [`.try_view_bits::<O>()`] method which delegates to this function and |
| /// may be more convenient for you to write. |
| /// |
| /// This is *very hard*, if not impossible, to cause to fail. Rust will not |
| /// create excessive arrays on 64-bit architectures. |
| /// |
| /// ## Parameters |
| /// |
| /// - `slice`: A shared reference to a slice of memory elements. |
| /// |
| /// ## Returns |
| /// |
| /// A shared `&BitSlice` over `slice`. If `slice` is longer than can be |
| /// encoded into a `&BitSlice` (see [`MAX_ELTS`]), this will fail and return |
| /// the original `slice` as an error. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let data = [0u8, 1]; |
| /// let bits = BitSlice::<_, Msb0>::try_from_slice(&data).unwrap(); |
| /// assert!(bits[15]); |
| /// |
| /// let bits = data.try_view_bits::<Msb0>().unwrap(); |
| /// ``` |
| /// |
| /// [`BitView`]: crate::view::BitView |
| /// [`MAX_ELTS`]: Self::MAX_ELTS |
| /// [`.try_view_bits::<O>()`]: crate::view::BitView::try_view_bits |
| #[inline] |
| pub fn try_from_slice(slice: &[T]) -> Result<&Self, BitSpanError<T>> { |
| let elts = slice.len(); |
| if elts >= Self::MAX_ELTS { |
| elts.saturating_mul(mem::bits_of::<T::Mem>()) |
| .pipe(BitSpanError::TooLong) |
| .pipe(Err) |
| } |
| else { |
| Ok(unsafe { Self::from_slice_unchecked(slice) }) |
| } |
| } |
| |
| /// Constructs an exclusive `&mut BitSlice` reference over a slice of |
| /// elements. |
| /// |
| /// The [`BitView`] trait, implemented on all `[T]` slices, provides a |
| /// [`.view_bits_mut::<O>()`] method which delegates to this function and |
| /// may be more convenient for you to write. |
| /// |
| /// ## Parameters |
| /// |
| /// - `slice`: An exclusive reference to a slice of memory elements. |
| /// |
| /// ## Returns |
| /// |
| /// An exclusive `&mut BitSlice` over all of `slice`. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if `slice` is too long to encode as a bit-slice view. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut data = [0u16; 2]; |
| /// let bits = BitSlice::<_, Lsb0>::from_slice_mut(&mut data); |
| /// bits.set(0, true); |
| /// bits.set(17, true); |
| /// assert_eq!(data, [1, 2]); |
| /// |
| /// let bits = data.view_bits_mut::<Lsb0>(); |
| /// ``` |
| /// |
| /// [`BitView`]: crate::view::BitView |
| /// [`.view_bits_mut::<O>()`]: crate::view::BitView::view_bits_mut |
| #[inline] |
| pub fn from_slice_mut(slice: &mut [T]) -> &mut Self { |
| Self::try_from_slice_mut(slice).unwrap() |
| } |
| |
| /// Attempts to construct an exclusive `&mut BitSlice` reference over a |
| /// slice of elements. |
| /// |
| /// The [`BitView`] trait, implemented on all `[T]` slices, provides a |
| /// [`.try_view_bits_mut::<O>()`] method which delegates to this function |
| /// and may be more convenient for you to write. |
| /// |
| /// ## Parameters |
| /// |
| /// - `slice`: An exclusive reference to a slice of memory elements. |
| /// |
| /// ## Returns |
| /// |
| /// An exclusive `&mut BitSlice` over `slice`. If `slice` is longer than can |
| /// be encoded into a `&mut BitSlice` (see [`MAX_ELTS`]), this will fail and |
| /// return the original `slice` as an error. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut data = [0u8; 2]; |
| /// let bits = BitSlice::<_, Msb0>::try_from_slice_mut(&mut data).unwrap(); |
| /// bits.set(7, true); |
| /// bits.set(15, true); |
| /// assert_eq!(data, [1; 2]); |
| /// |
| /// let bits = data.try_view_bits_mut::<Msb0>().unwrap(); |
| /// ``` |
| /// |
| /// [`BitView`]: crate::view::BitView |
| /// [`MAX_ELTS`]: Self::MAX_ELTS |
| /// [`.try_view_bits_mut::<O>()`]: crate::view::BitView::try_view_bits_mut |
| #[inline] |
| pub fn try_from_slice_mut( |
| slice: &mut [T], |
| ) -> Result<&mut Self, BitSpanError<T>> { |
| let elts = slice.len(); |
| if elts >= Self::MAX_ELTS { |
| elts.saturating_mul(mem::bits_of::<T::Mem>()) |
| .pipe(BitSpanError::TooLong) |
| .pipe(Err) |
| } |
| else { |
| Ok(unsafe { Self::from_slice_unchecked_mut(slice) }) |
| } |
| } |
| |
| /// Constructs a shared `&BitSlice` over an element slice, without checking |
| /// its length. |
| /// |
| /// If `slice` is too long to encode into a `&BitSlice`, then the produced |
| /// bit-slice’s length is unspecified. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `slice.len() < BitSlice::MAX_ELTS`. |
| /// |
| /// Calling this function with an over-long slice is **library-level** |
| /// undefined behavior. You may not assume anything about its implementation |
| /// or behavior, and must conservatively assume that over-long slices cause |
| /// compiler UB. |
| #[inline] |
| pub unsafe fn from_slice_unchecked(slice: &[T]) -> &Self { |
| let bits = slice.len().wrapping_mul(mem::bits_of::<T::Mem>()); |
| BitPtr::from_slice(slice) |
| .span_unchecked(bits) |
| .into_bitslice_ref() |
| } |
| |
| /// Constructs an exclusive `&mut BitSlice` over an element slice, without |
| /// checking its length. |
| /// |
| /// If `slice` is too long to encode into a `&mut BitSlice`, then the |
| /// produced bit-slice’s length is unspecified. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `slice.len() < BitSlice::MAX_ELTS`. |
| /// |
| /// Calling this function with an over-long slice is **library-level** |
| /// undefined behavior. You may not assume anything about its implementation |
| /// or behavior, and must conservatively assume that over-long slices cause |
| /// compiler UB. |
| #[inline] |
| pub unsafe fn from_slice_unchecked_mut(slice: &mut [T]) -> &mut Self { |
| let bits = slice.len().wrapping_mul(mem::bits_of::<T::Mem>()); |
| BitPtr::from_slice_mut(slice) |
| .span_unchecked(bits) |
| .into_bitslice_mut() |
| } |
| } |
| |
| /// Alternates of standard APIs. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Gets a raw pointer to the zeroth bit of the bit-slice. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::as_ptr`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr) |
| /// |
| /// ## API Differences |
| /// |
| /// This is renamed in order to indicate that it is returning a `bitvec` |
| /// structure, not a raw pointer. |
| #[inline] |
| pub fn as_bitptr(&self) -> BitPtr<Const, T, O> { |
| self.as_bitspan().to_bitptr() |
| } |
| |
| /// Gets a raw, write-capable pointer to the zeroth bit of the bit-slice. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::as_mut_ptr`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr) |
| /// |
| /// ## API Differences |
| /// |
| /// This is renamed in order to indicate that it is returning a `bitvec` |
| /// structure, not a raw pointer. |
| #[inline] |
| pub fn as_mut_bitptr(&mut self) -> BitPtr<Mut, T, O> { |
| self.as_mut_bitspan().to_bitptr() |
| } |
| |
| /// Views the bit-slice as a half-open range of bit-pointers, to its first |
| /// bit *in* the bit-slice and first bit *beyond* it. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::as_ptr_range`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range) |
| /// |
| /// ## API Differences |
| /// |
| /// This is renamed to indicate that it returns a `bitvec` structure, rather |
| /// than an ordinary `Range`. |
| /// |
| /// ## Notes |
| /// |
| /// `BitSlice` does define a [`.as_ptr_range()`], which returns a |
| /// `Range<BitPtr>`. `BitPtrRange` has additional capabilities that |
| /// `Range<*const T>` and `Range<BitPtr>` do not. |
| /// |
| /// [`.as_ptr_range()`]: Self::as_ptr_range |
| #[inline] |
| pub fn as_bitptr_range(&self) -> BitPtrRange<Const, T, O> { |
| self.as_bitspan().to_bitptr_range() |
| } |
| |
| /// Views the bit-slice as a half-open range of write-capable bit-pointers, |
| /// to its first bit *in* the bit-slice and the first bit *beyond* it. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::as_mut_ptr_range`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range) |
| /// |
| /// ## API Differences |
| /// |
| /// This is renamed to indicate that it returns a `bitvec` structure, rather |
| /// than an ordinary `Range`. |
| /// |
| /// ## Notes |
| /// |
| /// `BitSlice` does define a [`.as_mut_ptr_range()`], which returns a |
| /// `Range<BitPtr>`. `BitPtrRange` has additional capabilities that |
| /// `Range<*mut T>` and `Range<BitPtr>` do not. |
| #[inline] |
| pub fn as_mut_bitptr_range(&mut self) -> BitPtrRange<Mut, T, O> { |
| self.as_mut_bitspan().to_bitptr_range() |
| } |
| |
| /// Copies the bits from `src` into `self`. |
| /// |
| /// `self` and `src` must have the same length. |
| /// |
| /// ## Performance |
| /// |
| /// If `src` has the same type arguments as `self`, it will use the same |
| /// implementation as [`.copy_from_bitslice()`]; if you know that this will |
| /// always be the case, you should prefer to use that method directly. |
| /// |
| /// Only `.copy_from_bitslice()` is *able* to perform acceleration; this |
| /// method is *always* required to perform a bit-by-bit crawl over both |
| /// bit-slices. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::clone_from_slice`](https://doc.rust-lang.org/std/primitive.slice.html#method.clone_from_slice) |
| /// |
| /// ## API Differences |
| /// |
| /// This is renamed to reflect that it copies from another bit-slice, not |
| /// from an element slice. |
| /// |
| /// In order to support general usage, it allows `src` to have different |
| /// type parameters than `self`, at the cost of performance optimizations. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if the two bit-slices have different lengths. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// ``` |
| /// |
| /// [`.copy_from_bitslice()`]: Self::copy_from_bitslice |
| #[inline] |
| pub fn clone_from_bitslice<T2, O2>(&mut self, src: &BitSlice<T2, O2>) |
| where |
| T2: BitStore, |
| O2: BitOrder, |
| { |
| assert_eq!( |
| self.len(), |
| src.len(), |
| "cloning between bit-slices requires equal lengths", |
| ); |
| |
| if let Some(that) = src.coerce::<T, O>() { |
| self.copy_from_bitslice(that); |
| } |
| // TODO(myrrlyn): Test if `<T::Mem, O>` matches `<T2::Mem, O>` and |
| // specialize cloning. |
| else { |
| for (to, bit) in self.as_mut_bitptr_range().zip(src.iter().by_vals()) |
| { |
| unsafe { |
| to.write(bit); |
| } |
| } |
| } |
| } |
| |
| /// Copies all bits from `src` into `self`, using batched acceleration when |
| /// possible. |
| /// |
| /// `self` and `src` must have the same length. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::copy_from_slice`](https://doc.rust-lang.org/std/primitive.slice.html#method.copy_from_slice) |
| /// |
| /// ## Panics |
| /// |
| /// This panics if the two bit-slices have different lengths. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// ``` |
| #[inline] |
| pub fn copy_from_bitslice(&mut self, src: &Self) { |
| assert_eq!( |
| self.len(), |
| src.len(), |
| "copying between bit-slices requires equal lengths", |
| ); |
| |
| let (to_head, from_head) = |
| (self.as_bitspan().head(), src.as_bitspan().head()); |
| if to_head == from_head { |
| match (self.domain_mut(), src.domain()) { |
| (Domain::Enclave(mut to), Domain::Enclave(from)) => { |
| to.store_value(from.load_value()); |
| }, |
| ( |
| Domain::Region { |
| head: to_head, |
| body: to_body, |
| tail: to_tail, |
| }, |
| Domain::Region { |
| head: from_head, |
| body: from_body, |
| tail: from_tail, |
| }, |
| ) => { |
| if let (Some(mut to), Some(from)) = (to_head, from_head) { |
| to.store_value(from.load_value()); |
| } |
| for (to, from) in to_body.iter_mut().zip(from_body) { |
| to.store_value(from.load_value()); |
| } |
| if let (Some(mut to), Some(from)) = (to_tail, from_tail) { |
| to.store_value(from.load_value()); |
| } |
| }, |
| _ => unreachable!( |
| "bit-slices with equal type parameters, lengths, and heads \ |
| will always have equal domains" |
| ), |
| } |
| } |
| if let (Some(this), Some(that)) = |
| (self.coerce_mut::<T, Lsb0>(), src.coerce::<T, Lsb0>()) |
| { |
| return this.sp_copy_from_bitslice(that); |
| } |
| if let (Some(this), Some(that)) = |
| (self.coerce_mut::<T, Msb0>(), src.coerce::<T, Msb0>()) |
| { |
| return this.sp_copy_from_bitslice(that); |
| } |
| for (to, bit) in self.as_mut_bitptr_range().zip(src.iter().by_vals()) { |
| unsafe { |
| to.write(bit); |
| } |
| } |
| } |
| |
| /// Swaps the contents of two bit-slices. |
| /// |
| /// `self` and `other` must have the same length. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::swap_with_slice`](https://doc.rust-lang.org/std/primitive.slice.html#method.swap_with_slice) |
| /// |
| /// ## API Differences |
| /// |
| /// This method is renamed, as it takes a bit-slice rather than an element |
| /// slice. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if the two bit-slices have different lengths. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut one = [0xA5u8, 0x69]; |
| /// let mut two = 0x1234u16; |
| /// let one_bits = one.view_bits_mut::<Msb0>(); |
| /// let two_bits = two.view_bits_mut::<Lsb0>(); |
| /// |
| /// one_bits.swap_with_bitslice(two_bits); |
| /// |
| /// assert_eq!(one, [0x2C, 0x48]); |
| /// # if cfg!(target_endian = "little") { |
| /// assert_eq!(two, 0x96A5); |
| /// # } |
| /// ``` |
| #[inline] |
| pub fn swap_with_bitslice<T2, O2>(&mut self, other: &mut BitSlice<T2, O2>) |
| where |
| T2: BitStore, |
| O2: BitOrder, |
| { |
| assert_eq!( |
| self.len(), |
| other.len(), |
| "swapping between bit-slices requires equal lengths", |
| ); |
| |
| if let (Some(this), Some(that)) = |
| (self.coerce_mut::<T, Lsb0>(), other.coerce_mut::<T, Lsb0>()) |
| { |
| return this.sp_swap_with_bitslice(that); |
| } |
| if let (Some(this), Some(that)) = |
| (self.coerce_mut::<T, Msb0>(), other.coerce_mut::<T, Msb0>()) |
| { |
| return this.sp_swap_with_bitslice(that); |
| } |
| self.as_mut_bitptr_range() |
| .zip(other.as_mut_bitptr_range()) |
| .for_each(|(a, b)| unsafe { |
| bv_ptr::swap(a, b); |
| }); |
| } |
| } |
| |
| /// Extensions of standard APIs. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Writes a new value into a single bit. |
| /// |
| /// This is the replacement for `*slice[index] = value;`, as `bitvec` is not |
| /// able to express that under the current `IndexMut` API signature. |
| /// |
| /// ## Parameters |
| /// |
| /// - `&mut self` |
| /// - `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::*; |
| /// |
| /// let bits = bits![mut 0, 1]; |
| /// bits.set(0, true); |
| /// bits.set(1, false); |
| /// |
| /// assert_eq!(bits, bits![1, 0]); |
| /// ``` |
| #[inline] |
| pub fn set(&mut self, index: usize, value: bool) { |
| self.replace(index, value); |
| } |
| |
| /// Writes a new value into a single bit, without bounds checking. |
| /// |
| /// ## Parameters |
| /// |
| /// - `&mut self` |
| /// - `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`. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `index` is in the range `0 .. self.len()`. |
| /// |
| /// This performs bit-pointer offset arithmetic without doing any bounds |
| /// checks. If `index` is out of bounds, then this will issue an |
| /// out-of-bounds access and will trigger memory unsafety. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut data = 0u8; |
| /// let bits = &mut data.view_bits_mut::<Lsb0>()[.. 2]; |
| /// assert_eq!(bits.len(), 2); |
| /// unsafe { |
| /// bits.set_unchecked(3, true); |
| /// } |
| /// assert_eq!(data, 8); |
| /// ``` |
| #[inline] |
| pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) { |
| self.replace_unchecked(index, value); |
| } |
| |
| /// Writes a new value into a bit, and returns its previous value. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if `index` is not less than `self.len()`. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![mut 0]; |
| /// assert!(!bits.replace(0, true)); |
| /// assert!(bits[0]); |
| /// ``` |
| #[inline] |
| pub fn replace(&mut self, index: usize, value: bool) -> bool { |
| self.assert_in_bounds(index, 0 .. self.len()); |
| unsafe { self.replace_unchecked(index, value) } |
| } |
| |
| /// Writes a new value into a bit, returning the previous value, without |
| /// bounds checking. |
| /// |
| /// ## Safety |
| /// |
| /// `index` must be less than `self.len()`. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![mut 0, 0]; |
| /// let old = unsafe { |
| /// let a = &mut bits[.. 1]; |
| /// a.replace_unchecked(1, true) |
| /// }; |
| /// assert!(!old); |
| /// assert!(bits[1]); |
| /// ``` |
| #[inline] |
| pub unsafe fn replace_unchecked( |
| &mut self, |
| index: usize, |
| value: bool, |
| ) -> bool { |
| self.as_mut_bitptr().add(index).replace(value) |
| } |
| |
| /// Swaps two bits in a bit-slice, without bounds checking. |
| /// |
| /// See [`.swap()`] for documentation. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `a` and `b` are both in the range `0 .. |
| /// self.len()`. |
| /// |
| /// This method performs bit-pointer offset arithmetic without doing any |
| /// bounds checks. If `a` or `b` are out of bounds, then this will issue an |
| /// out-of-bounds access and will trigger memory unsafety. |
| /// |
| /// [`.swap()`]: Self::swap |
| #[inline] |
| pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { |
| let a = self.as_mut_bitptr().add(a); |
| let b = self.as_mut_bitptr().add(b); |
| bv_ptr::swap(a, b); |
| } |
| |
| /// Splits a bit-slice at an index, without bounds checking. |
| /// |
| /// See [`.split_at()`] for documentation. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `mid` is in the range `0 ..= self.len()`. |
| /// |
| /// This method produces new bit-slice references. If `mid` is out of |
| /// bounds, its behavior is **library-level** undefined. You must |
| /// conservatively assume that an out-of-bounds split point produces |
| /// compiler-level UB. |
| /// |
| /// [`.split_at()`]: Self::split_at |
| #[inline] |
| pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&Self, &Self) { |
| let len = self.len(); |
| let left = self.as_bitptr(); |
| let right = left.add(mid); |
| let left = left.span_unchecked(mid); |
| let right = right.span_unchecked(len - mid); |
| let left = left.into_bitslice_ref(); |
| let right = right.into_bitslice_ref(); |
| (left, right) |
| } |
| |
| /// Splits a mutable bit-slice at an index, without bounds checking. |
| /// |
| /// See [`.split_at_mut()`] for documentation. |
| /// |
| /// ## Safety |
| /// |
| /// You must ensure that `mid` is in the range `0 ..= self.len()`. |
| /// |
| /// This method produces new bit-slice references. If `mid` is out of |
| /// bounds, its behavior is **library-level** undefined. You must |
| /// conservatively assume that an out-of-bounds split point produces |
| /// compiler-level UB. |
| /// |
| /// [`.split_at_mut()`]: Self::split_at_mut |
| #[inline] |
| pub unsafe fn split_at_unchecked_mut( |
| &mut self, |
| mid: usize, |
| ) -> (&mut BitSlice<T::Alias, O>, &mut BitSlice<T::Alias, O>) { |
| let len = self.len(); |
| let left = self.alias_mut().as_mut_bitptr(); |
| let right = left.add(mid); |
| ( |
| left.span_unchecked(mid).into_bitslice_mut(), |
| right.span_unchecked(len - mid).into_bitslice_mut(), |
| ) |
| } |
| |
| /// Copies bits from one region of the bit-slice to another region of |
| /// itself, without doing bounds checks. |
| /// |
| /// The regions are allowed to overlap. |
| /// |
| /// ## Parameters |
| /// |
| /// - `&mut self` |
| /// - `src`: The range within `self` from which to copy. |
| /// - `dst`: The starting index within `self` at which to paste. |
| /// |
| /// ## Effects |
| /// |
| /// `self[src]` is copied to `self[dest .. dest + src.len()]`. The bits of |
| /// `self[src]` are in an unspecified, but initialized, state. |
| /// |
| /// ## Safety |
| /// |
| /// `src.end()` and `dest + src.len()` must be entirely within bounds. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let mut data = 0b1011_0000u8; |
| /// let bits = data.view_bits_mut::<Msb0>(); |
| /// |
| /// unsafe { |
| /// bits.copy_within_unchecked(.. 4, 2); |
| /// } |
| /// assert_eq!(data, 0b1010_1100); |
| /// ``` |
| #[inline] |
| pub unsafe fn copy_within_unchecked<R>(&mut self, src: R, dest: usize) |
| where R: RangeExt<usize> { |
| if let Some(this) = self.coerce_mut::<T, Lsb0>() { |
| return this.sp_copy_within_unchecked(src, dest); |
| } |
| if let Some(this) = self.coerce_mut::<T, Msb0>() { |
| return this.sp_copy_within_unchecked(src, dest); |
| } |
| let source = src.normalize(0, self.len()); |
| let source_len = source.len(); |
| let rev = source.contains(&dest); |
| let dest = dest .. dest + source_len; |
| for (from, to) in self |
| .get_unchecked(source) |
| .as_bitptr_range() |
| .zip(self.get_unchecked_mut(dest).as_mut_bitptr_range()) |
| .bidi(rev) |
| { |
| to.write(from.read()); |
| } |
| } |
| |
| #[inline] |
| #[doc(hidden)] |
| #[cfg(not(tarpaulin_include))] |
| #[deprecated = "use `.iter_mut().enumerate()`"] |
| pub fn for_each(&mut self, mut func: impl FnMut(usize, bool) -> bool) { |
| for (idx, ptr) in self.as_mut_bitptr_range().enumerate() { |
| unsafe { |
| ptr.write(func(idx, ptr.read())); |
| } |
| } |
| } |
| } |
| |
| /// Views of underlying memory. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Partitions a bit-slice into maybe-contended and known-uncontended parts. |
| /// |
| /// The documentation of `BitDomain` goes into this in more detail. In |
| /// short, this produces a `&BitSlice` that is as large as possible without |
| /// requiring alias protection, as well as any bits that were not able to be |
| /// included in the unaliased bit-slice. |
| #[inline] |
| #[cfg(not(tarpaulin_include))] |
| pub fn bit_domain(&self) -> BitDomain<Const, T, O> { |
| self.domain().into_bit_domain() |
| } |
| |
| /// Partitions a mutable bit-slice into maybe-contended and |
| /// known-uncontended parts. |
| /// |
| /// The documentation of `BitDomain` goes into this in more detail. In |
| /// short, this produces a `&mut BitSlice` that is as large as possible |
| /// without requiring alias protection, as well as any bits that were not |
| /// able to be included in the unaliased bit-slice. |
| #[inline] |
| #[cfg(not(tarpaulin_include))] |
| pub fn bit_domain_mut(&mut self) -> BitDomain<Mut, T, O> { |
| self.domain_mut().into_bit_domain() |
| } |
| |
| /// Views the underlying memory of a bit-slice, removing alias protections |
| /// where possible. |
| /// |
| /// The documentation of `Domain` goes into this in more detail. In short, |
| /// this produces a `&[T]` slice with alias protections removed, covering |
| /// all elements that `self` completely fills. Partially-used elements on |
| /// either the front or back edge of the slice are returned separately. |
| #[inline] |
| #[cfg(not(tarpaulin_include))] |
| pub fn domain(&self) -> Domain<Const, T, O> { |
| Domain::new(self) |
| } |
| |
| /// Views the underlying memory of a bit-slice, removing alias protections |
| /// where possible. |
| /// |
| /// The documentation of `Domain` goes into this in more detail. In short, |
| /// this produces a `&mut [T]` slice with alias protections removed, |
| /// covering all elements that `self` completely fills. Partially-used |
| /// elements on the front or back edge of the slice are returned separately. |
| #[inline] |
| #[cfg(not(tarpaulin_include))] |
| pub fn domain_mut(&mut self) -> Domain<Mut, T, O> { |
| Domain::new(self) |
| } |
| } |
| |
| /// Bit-value queries. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Counts the number of bits set to `1` in the bit-slice contents. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![1, 1, 0, 0]; |
| /// assert_eq!(bits[.. 2].count_ones(), 2); |
| /// assert_eq!(bits[2 ..].count_ones(), 0); |
| /// assert_eq!(bits![].count_ones(), 0); |
| /// ``` |
| #[inline] |
| pub fn count_ones(&self) -> usize { |
| match self.domain() { |
| Domain::Enclave(elem) => elem.load_value().count_ones() as usize, |
| Domain::Region { head, body, tail } => { |
| head.map_or(0, |elem| elem.load_value().count_ones() as usize) |
| + body |
| .iter() |
| .map(BitStore::load_value) |
| .map(|elem| elem.count_ones() as usize) |
| .sum::<usize>() + tail |
| .map_or(0, |elem| elem.load_value().count_ones() as usize) |
| }, |
| } |
| } |
| |
| /// Counts the number of bits cleared to `0` in the bit-slice contents. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![1, 1, 0, 0]; |
| /// assert_eq!(bits[.. 2].count_zeros(), 0); |
| /// assert_eq!(bits[2 ..].count_zeros(), 2); |
| /// assert_eq!(bits![].count_zeros(), 0); |
| /// ``` |
| #[inline] |
| pub fn count_zeros(&self) -> usize { |
| match self.domain() { |
| Domain::Enclave(elem) => (elem.load_value() |
| | !elem.mask().into_inner()) |
| .count_zeros() as usize, |
| Domain::Region { head, body, tail } => { |
| head.map_or(0, |elem| { |
| (elem.load_value() | !elem.mask().into_inner()).count_zeros() |
| as usize |
| }) + body |
| .iter() |
| .map(BitStore::load_value) |
| .map(|elem| elem.count_zeros() as usize) |
| .sum::<usize>() + tail.map_or(0, |elem| { |
| (elem.load_value() | !elem.mask().into_inner()).count_zeros() |
| as usize |
| }) |
| }, |
| } |
| } |
| |
| /// Enumerates the index of each bit in a bit-slice set to `1`. |
| /// |
| /// This is a shorthand for a `.enumerate().filter_map()` iterator that |
| /// selects the index of each `true` bit; however, its implementation is |
| /// eligible for optimizations that the individual-bit iterator is not. |
| /// |
| /// Specializations for the `Lsb0` and `Msb0` orderings allow processors |
| /// with instructions that seek particular bits within an element to operate |
| /// on whole elements, rather than on each bit individually. |
| /// |
| /// ## Examples |
| /// |
| /// This example uses `.iter_ones()`, a `.filter_map()` that finds the index |
| /// of each set bit, and the known indices, in order to show that they have |
| /// equivalent behavior. |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![0, 1, 0, 0, 1, 0, 0, 0, 1]; |
| /// |
| /// let iter_ones = bits.iter_ones(); |
| /// let known_indices = [1, 4, 8].iter().copied(); |
| /// let filter = bits.iter() |
| /// .by_vals() |
| /// .enumerate() |
| /// .filter_map(|(idx, bit)| if bit { Some(idx) } else { None }); |
| /// let all = iter_ones.zip(known_indices).zip(filter); |
| /// |
| /// for ((iter_one, known), filtered) in all { |
| /// assert_eq!(iter_one, known); |
| /// assert_eq!(known, filtered); |
| /// } |
| /// ``` |
| #[inline] |
| pub fn iter_ones(&self) -> IterOnes<T, O> { |
| IterOnes::new(self) |
| } |
| |
| /// Enumerates the index of each bit in a bit-slice cleared to `0`. |
| /// |
| /// This is a shorthand for a `.enumerate().filter_map()` iterator that |
| /// selects the index of each `false` bit; however, its implementation is |
| /// eligible for optimizations that the individual-bit iterator is not. |
| /// |
| /// Specializations for the `Lsb0` and `Msb0` orderings allow processors |
| /// with instructions that seek particular bits within an element to operate |
| /// on whole elements, rather than on each bit individually. |
| /// |
| /// ## Examples |
| /// |
| /// This example uses `.iter_zeros()`, a `.filter_map()` that finds the |
| /// index of each cleared bit, and the known indices, in order to show that |
| /// they have equivalent behavior. |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![1, 0, 1, 1, 0, 1, 1, 1, 0]; |
| /// |
| /// let iter_zeros = bits.iter_zeros(); |
| /// let known_indices = [1, 4, 8].iter().copied(); |
| /// let filter = bits.iter() |
| /// .by_vals() |
| /// .enumerate() |
| /// .filter_map(|(idx, bit)| if !bit { Some(idx) } else { None }); |
| /// let all = iter_zeros.zip(known_indices).zip(filter); |
| /// |
| /// for ((iter_zero, known), filtered) in all { |
| /// assert_eq!(iter_zero, known); |
| /// assert_eq!(known, filtered); |
| /// } |
| /// ``` |
| #[inline] |
| pub fn iter_zeros(&self) -> IterZeros<T, O> { |
| IterZeros::new(self) |
| } |
| |
| /// Finds the index of the first bit in the bit-slice set to `1`. |
| /// |
| /// Returns `None` if there is no `true` bit in the bit-slice. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(bits![].first_one().is_none()); |
| /// assert!(bits![0].first_one().is_none()); |
| /// assert_eq!(bits![0, 1].first_one(), Some(1)); |
| /// ``` |
| #[inline] |
| pub fn first_one(&self) -> Option<usize> { |
| self.iter_ones().next() |
| } |
| |
| /// Finds the index of the first bit in the bit-slice cleared to `0`. |
| /// |
| /// Returns `None` if there is no `false` bit in the bit-slice. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(bits![].first_zero().is_none()); |
| /// assert!(bits![1].first_zero().is_none()); |
| /// assert_eq!(bits![1, 0].first_zero(), Some(1)); |
| /// ``` |
| #[inline] |
| pub fn first_zero(&self) -> Option<usize> { |
| self.iter_zeros().next() |
| } |
| |
| /// Finds the index of the last bit in the bit-slice set to `1`. |
| /// |
| /// Returns `None` if there is no `true` bit in the bit-slice. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(bits![].last_one().is_none()); |
| /// assert!(bits![0].last_one().is_none()); |
| /// assert_eq!(bits![1, 0].last_one(), Some(0)); |
| /// ``` |
| #[inline] |
| pub fn last_one(&self) -> Option<usize> { |
| self.iter_ones().next_back() |
| } |
| |
| /// Finds the index of the last bit in the bit-slice cleared to `0`. |
| /// |
| /// Returns `None` if there is no `false` bit in the bit-slice. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(bits![].last_zero().is_none()); |
| /// assert!(bits![1].last_zero().is_none()); |
| /// assert_eq!(bits![0, 1].last_zero(), Some(0)); |
| /// ``` |
| #[inline] |
| pub fn last_zero(&self) -> Option<usize> { |
| self.iter_zeros().next_back() |
| } |
| |
| /// Counts the number of bits from the start of the bit-slice to the first |
| /// bit set to `0`. |
| /// |
| /// This returns `0` if the bit-slice is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert_eq!(bits![].leading_ones(), 0); |
| /// assert_eq!(bits![0].leading_ones(), 0); |
| /// assert_eq!(bits![1, 0].leading_ones(), 1); |
| /// ``` |
| #[inline] |
| pub fn leading_ones(&self) -> usize { |
| self.first_zero().unwrap_or_else(|| self.len()) |
| } |
| |
| /// Counts the number of bits from the start of the bit-slice to the first |
| /// bit set to `1`. |
| /// |
| /// This returns `0` if the bit-slice is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert_eq!(bits![].leading_zeros(), 0); |
| /// assert_eq!(bits![1].leading_zeros(), 0); |
| /// assert_eq!(bits![0, 1].leading_zeros(), 1); |
| /// ``` |
| #[inline] |
| pub fn leading_zeros(&self) -> usize { |
| self.first_one().unwrap_or_else(|| self.len()) |
| } |
| |
| /// Counts the number of bits from the end of the bit-slice to the last bit |
| /// set to `0`. |
| /// |
| /// This returns `0` if the bit-slice is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert_eq!(bits![].trailing_ones(), 0); |
| /// assert_eq!(bits![0].trailing_ones(), 0); |
| /// assert_eq!(bits![0, 1].trailing_ones(), 1); |
| /// ``` |
| #[inline] |
| pub fn trailing_ones(&self) -> usize { |
| let len = self.len(); |
| self.last_zero().map(|idx| len - 1 - idx).unwrap_or(len) |
| } |
| |
| /// Counts the number of bits from the end of the bit-slice to the last bit |
| /// set to `1`. |
| /// |
| /// This returns `0` if the bit-slice is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert_eq!(bits![].trailing_zeros(), 0); |
| /// assert_eq!(bits![1].trailing_zeros(), 0); |
| /// assert_eq!(bits![1, 0].trailing_zeros(), 1); |
| /// ``` |
| #[inline] |
| pub fn trailing_zeros(&self) -> usize { |
| let len = self.len(); |
| self.last_one().map(|idx| len - 1 - idx).unwrap_or(len) |
| } |
| |
| /// Tests if there is at least one bit set to `1` in the bit-slice. |
| /// |
| /// Returns `false` when `self` is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(!bits![].any()); |
| /// assert!(!bits![0].any()); |
| /// assert!(bits![0, 1].any()); |
| /// ``` |
| #[inline] |
| pub fn any(&self) -> bool { |
| self.count_ones() > 0 |
| } |
| |
| /// Tests if every bit is set to `1` in the bit-slice. |
| /// |
| /// Returns `true` when `self` is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!( bits![].all()); |
| /// assert!(!bits![0].all()); |
| /// assert!( bits![1].all()); |
| /// ``` |
| #[inline] |
| pub fn all(&self) -> bool { |
| self.count_zeros() == 0 |
| } |
| |
| /// Tests if every bit is cleared to `0` in the bit-slice. |
| /// |
| /// Returns `true` when `self` is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!( bits![].not_any()); |
| /// assert!(!bits![1].not_any()); |
| /// assert!( bits![0].not_any()); |
| /// ``` |
| #[inline] |
| pub fn not_any(&self) -> bool { |
| self.count_ones() == 0 |
| } |
| |
| /// Tests if at least one bit is cleared to `0` in the bit-slice. |
| /// |
| /// Returns `false` when `self` is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(!bits![].not_all()); |
| /// assert!(!bits![1].not_all()); |
| /// assert!( bits![0].not_all()); |
| /// ``` |
| #[inline] |
| pub fn not_all(&self) -> bool { |
| self.count_zeros() > 0 |
| } |
| |
| /// Tests if at least one bit is set to `1`, and at least one bit is cleared |
| /// to `0`, in the bit-slice. |
| /// |
| /// Returns `false` when `self` is empty. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// assert!(!bits![].some()); |
| /// assert!(!bits![0].some()); |
| /// assert!(!bits![1].some()); |
| /// assert!( bits![0, 1].some()); |
| /// ``` |
| #[inline] |
| pub fn some(&self) -> bool { |
| self.any() && self.not_all() |
| } |
| } |
| |
| /// Buffer manipulation. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Shifts the contents of a bit-slice “left” (towards the zero-index), |
| /// clearing the “right” bits to `0`. |
| /// |
| /// This is a strictly-worse analogue to taking `bits = &bits[by ..]`: it |
| /// has to modify the entire memory region that `bits` governs, and destroys |
| /// contained information. Unless the actual memory layout and contents of |
| /// your bit-slice matters to your program, you should *probably* prefer to |
| /// munch your way forward through a bit-slice handle. |
| /// |
| /// Note also that the “left” here is semantic only, and **does not** |
| /// necessarily correspond to a left-shift instruction applied to the |
| /// underlying integer storage. |
| /// |
| /// This has no effect when `by` is `0`. When `by` is `self.len()`, the |
| /// bit-slice is entirely cleared to `0`. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if `by` is not less than `self.len()`. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![mut 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1]; |
| /// // these bits are retained ^--------------------------^ |
| /// bits.shift_left(2); |
| /// assert_eq!(bits, bits![1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0]); |
| /// // and move here ^--------------------------^ |
| /// |
| /// let bits = bits![mut 1; 2]; |
| /// bits.shift_left(2); |
| /// assert_eq!(bits, bits![0; 2]); |
| /// ``` |
| #[inline] |
| pub fn shift_left(&mut self, by: usize) { |
| if by == 0 { |
| return; |
| } |
| |
| let len = self.len(); |
| if by == len { |
| return self.fill(false); |
| } |
| assert!( |
| by <= len, |
| "shift must be less than the length of the bit-slice: {} >= {}", |
| by, |
| len, |
| ); |
| |
| unsafe { |
| self.copy_within_unchecked(by .., 0); |
| self.get_unchecked_mut(len - by ..).fill(false); |
| } |
| } |
| |
| /// Shifts the contents of a bit-slice “right” (away from the zero-index), |
| /// clearing the “left” bits to `0`. |
| /// |
| /// This is a strictly-worse analogue to taking `bits = &bits[.. bits.len() |
| /// - by]`: it must modify the entire memory region that `bits` governs, and |
| /// destroys contained information. Unless the actual memory layout and |
| /// contents of your bit-slice matters to your program, you should |
| /// *probably* prefer to munch your way backward through a bit-slice handle. |
| /// |
| /// Note also that the “right” here is semantic only, and **does not** |
| /// necessarily correspond to a right-shift instruction applied to the |
| /// underlying integer storage. |
| /// |
| /// This has no effect when `by` is `0`. When `by` is `self.len()`, the |
| /// bit-slice is entirely cleared to `0`. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if `by` is not less than `self.len()`. |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![mut 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1]; |
| /// // these bits stay ^--------------------------^ |
| /// bits.shift_right(2); |
| /// assert_eq!(bits, bits![0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1]); |
| /// // and move here ^--------------------------^ |
| /// |
| /// let bits = bits![mut 1; 2]; |
| /// bits.shift_right(2); |
| /// assert_eq!(bits, bits![0; 2]); |
| /// ``` |
| #[inline] |
| pub fn shift_right(&mut self, by: usize) { |
| if by == 0 { |
| return; |
| } |
| |
| let len = self.len(); |
| if by == len { |
| return self.fill(false); |
| } |
| assert!( |
| by <= len, |
| "shift must be less than the length of the bit-slice: {} >= {}", |
| by, |
| len, |
| ); |
| |
| unsafe { |
| self.copy_within_unchecked(.. len - by, by); |
| self.get_unchecked_mut(.. by).fill(false); |
| } |
| } |
| } |
| |
| /// Crate internals. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Gets the structural form of the encoded reference. |
| pub(crate) fn as_bitspan(&self) -> BitSpan<Const, T, O> { |
| BitSpan::from_bitslice_ptr(self) |
| } |
| |
| /// Gets the structural form of the encoded reference. |
| pub(crate) fn as_mut_bitspan(&mut self) -> BitSpan<Mut, T, O> { |
| BitSpan::from_bitslice_ptr_mut(self) |
| } |
| |
| /// Asserts that `index` is within the given bounds. |
| /// |
| /// ## Parameters |
| /// |
| /// - `&self` |
| /// - `index`: The bit index to test against the bit-slice. |
| /// - `bounds`: The bounds to check. cannot exceed `0 ..= self.len()`. |
| /// |
| /// ## Panics |
| /// |
| /// This panics if `bounds` is outside `index`. |
| pub(crate) fn assert_in_bounds<R>(&self, index: usize, bounds: R) |
| where R: RangeExt<usize> { |
| let bounds = bounds.normalize(0, self.len()); |
| assert!( |
| bounds.contains(&index), |
| "index {} out of range: {:?}", |
| index, |
| bounds.end_bound() |
| ); |
| } |
| |
| /// Marks an exclusive bit-slice as covering an aliased memory region. |
| pub(crate) fn alias_mut(&mut self) -> &mut BitSlice<T::Alias, O> { |
| unsafe { self.as_mut_bitspan().cast::<T::Alias>().into_bitslice_mut() } |
| } |
| |
| /// Removes an aliasing marker from an exclusive bit-slice handle. |
| /// |
| /// ## Safety |
| /// |
| /// This may only be used when the bit-slice is either known to be |
| /// unaliased, or this call is combined with an operation that adds an |
| /// aliasing marker and the total number of aliasing markers remains |
| /// unchanged. |
| pub(crate) unsafe fn unalias_mut( |
| this: &mut BitSlice<T::Alias, O>, |
| ) -> &mut Self { |
| this.as_mut_bitspan().cast::<T>().into_bitslice_mut() |
| } |
| |
| /// Splits a mutable bit-slice at a midpoint, without either doing bounds |
| /// checks or adding an alias marker to the returned sections. |
| /// |
| /// This method has the same behavior as [`.split_at_unchecked_mut()`], |
| /// except that it does not apply an aliasing marker to the partitioned |
| /// subslices. |
| /// |
| /// ## Safety |
| /// |
| /// See `split_at_unchecked_mut`. Additionally, this is only safe when `T` |
| /// is alias-safe. |
| /// |
| /// [`.split_at_unchecked_mut()`]: Self::split_at_unchecked_mut |
| pub(crate) unsafe fn split_at_unchecked_mut_noalias( |
| &mut self, |
| mid: usize, |
| ) -> (&mut Self, &mut Self) { |
| // Split the slice at the requested midpoint, adding an alias layer |
| let (head, tail) = self.split_at_unchecked_mut(mid); |
| // Remove the new alias layer. |
| (Self::unalias_mut(head), Self::unalias_mut(tail)) |
| } |
| } |
| |
| /// Methods available only when `T` allows shared mutability. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore + radium::Radium, |
| O: BitOrder, |
| { |
| /// Writes a new value into a single bit, using alias-safe operations. |
| /// |
| /// This is equivalent to [`.set()`], 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]; |
| /// bits.set_aliased(0, true); |
| /// bits.set_aliased(1, false); |
| /// |
| /// assert_eq!(bits, bits![1, 0]); |
| /// ``` |
| /// |
| /// [`.set()`]: Self::set |
| #[inline] |
| pub fn set_aliased(&self, index: usize, value: bool) { |
| self.assert_in_bounds(index, 0 .. self.len()); |
| unsafe { |
| self.set_aliased_unchecked(index, value); |
| } |
| } |
| |
| /// Writes a new value into a single bit, using alias-safe operations and |
| /// without bounds checking. |
| /// |
| /// This is equivalent to [`.set_unchecked()`], 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`. |
| /// |
| /// ## 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]; |
| /// unsafe { |
| /// bits.set_aliased_unchecked(3, true); |
| /// } |
| /// assert_eq!(data.get(), 8); |
| /// ``` |
| /// |
| /// [`.set_unchecked()`]: Self::set_unchecked |
| #[inline] |
| pub unsafe fn set_aliased_unchecked(&self, index: usize, value: bool) { |
| self.as_bitptr().add(index).freeze().frozen_write_bit(value); |
| } |
| } |
| |
| /// Miscellaneous information. |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// The inclusive maximum length of a `BitSlice<_, T>`. |
| /// |
| /// As `BitSlice` is zero-indexed, the largest possible *index* is one less |
| /// than this value. |
| /// |
| /// |CPU word width| Value | |
| /// |-------------:|----------------------:| |
| /// | 32 bits | `0x1fff_ffff` | |
| /// | 64 bits |`0x1fff_ffff_ffff_ffff`| |
| pub const MAX_BITS: usize = BitSpan::<Const, T, O>::REGION_MAX_BITS; |
| /// The inclusive maximum length that a `[T]` slice can be for |
| /// `BitSlice<_, T>` to cover it. |
| /// |
| /// A `BitSlice<_, T>` that begins in the interior of an element and |
| /// contains the maximum number of bits will extend one element past the |
| /// cutoff that would occur if the bit-slice began at the zeroth bit. Such a |
| /// bit-slice is difficult to manually construct, but would not otherwise |
| /// fail. |
| /// |
| /// |Type Bits|Max Elements (32-bit)| Max Elements (64-bit) | |
| /// |--------:|--------------------:|----------------------:| |
| /// | 8| `0x0400_0001` |`0x0400_0000_0000_0001`| |
| /// | 16| `0x0200_0001` |`0x0200_0000_0000_0001`| |
| /// | 32| `0x0100_0001` |`0x0100_0000_0000_0001`| |
| /// | 64| `0x0080_0001` |`0x0080_0000_0000_0001`| |
| pub const MAX_ELTS: usize = BitSpan::<Const, T, O>::REGION_MAX_ELTS; |
| } |
| |
| #[cfg(feature = "alloc")] |
| impl<T, O> BitSlice<T, O> |
| where |
| T: BitStore, |
| O: BitOrder, |
| { |
| /// Copies a bit-slice into an owned bit-vector. |
| /// |
| /// Since the new vector is freshly owned, this gets marked as `::Unalias` |
| /// to remove any guards that may have been inserted by the bit-slice’s |
| /// history. |
| /// |
| /// It does *not* use the underlying memory type, so that a `BitSlice<_, |
| /// Cell<_>>` will produce a `BitVec<_, Cell<_>>`. |
| /// |
| /// ## Original |
| /// |
| /// [`slice::to_vec`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec) |
| /// |
| /// ## Examples |
| /// |
| /// ```rust |
| /// use bitvec::prelude::*; |
| /// |
| /// let bits = bits![0, 1, 0, 1]; |
| /// let bv = bits.to_bitvec(); |
| /// assert_eq!(bits, bv); |
| /// ``` |
| #[inline] |
| pub fn to_bitvec(&self) -> BitVec<T::Unalias, O> { |
| self.domain() |
| .map(<T::Unalias as BitStore>::new) |
| .collect::<Vec<_>>() |
| .pipe(BitVec::from_vec) |
| .tap_mut(|bv| unsafe { |
| bv.set_head(self.as_bitspan().head()); |
| bv.set_len(self.len()); |
| }) |
| } |
| } |
| |
| #[inline] |
| #[doc = include_str!("../doc/slice/from_raw_parts_unchecked.md")] |
| pub unsafe fn from_raw_parts_unchecked<'a, T, O>( |
| ptr: BitPtr<Const, T, O>, |
| len: usize, |
| ) -> &'a BitSlice<T, O> |
| where |
| O: BitOrder, |
| T: 'a + BitStore, |
| { |
| ptr.span_unchecked(len).into_bitslice_ref() |
| } |
| |
| #[inline] |
| #[doc = include_str!("../doc/slice/from_raw_parts_unchecked_mut.md")] |
| pub unsafe fn from_raw_parts_unchecked_mut<'a, T, O>( |
| ptr: BitPtr<Mut, T, O>, |
| len: usize, |
| ) -> &'a mut BitSlice<T, O> |
| where |
| O: BitOrder, |
| T: 'a + BitStore, |
| { |
| ptr.span_unchecked(len).into_bitslice_mut() |
| } |