+1281
| /*! Bit management | ||
| The `BitStore` trait defines constants and associated functions suitable for | ||
| managing the bit patterns of a fundamental, and is the constraint for the | ||
| storage type of the data structures of the rest of the crate. | ||
| The other types in this module provide stronger rules about how indices map to | ||
| concrete bits in fundamental elements. They are implementation details, and are | ||
| not exported in the prelude. | ||
| !*/ | ||
| use crate::cursor::Cursor; | ||
| use core::{ | ||
| cmp::Eq, | ||
| convert::From, | ||
| fmt::{ | ||
| self, | ||
| Binary, | ||
| Debug, | ||
| Display, | ||
| Formatter, | ||
| LowerHex, | ||
| UpperHex, | ||
| }, | ||
| marker::{ | ||
| Send, | ||
| Sync, | ||
| }, | ||
| mem::size_of, | ||
| ops::{ | ||
| BitAnd, | ||
| BitAndAssign, | ||
| BitOrAssign, | ||
| Deref, | ||
| DerefMut, | ||
| Not, | ||
| Shl, | ||
| ShlAssign, | ||
| Shr, | ||
| ShrAssign, | ||
| }, | ||
| }; | ||
| #[cfg(feature = "atomic")] | ||
| use crate::atomic::Atomic; | ||
| #[cfg(feature = "atomic")] | ||
| use core::sync::atomic; | ||
| /** Generalizes over the fundamental types for use in `bitvec` data structures. | ||
| This trait must only be implemented on unsigned integer primitives with full | ||
| alignment. It cannot be implemented on `u128` on any architecture, or on `u64` | ||
| on 32-bit systems. | ||
| The `Sealed` supertrait ensures that this can only be implemented locally, and | ||
| will never be implemented by downstream crates on new types. | ||
| **/ | ||
| pub trait BitStore: | ||
| // Forbid external implementation | ||
| Sealed | ||
| + Binary | ||
| // Element-wise binary manipulation | ||
| + BitAnd<Self, Output=Self> | ||
| + BitAndAssign<Self> | ||
| + BitOrAssign<Self> | ||
| // Permit indexing into a generic array | ||
| + Copy | ||
| + Debug | ||
| + Display | ||
| // Permit testing a value against 1 in `get()`. | ||
| + Eq | ||
| // Rust treats numeric literals in code as vaguely typed and does not make | ||
| // them concrete until long after trait expansion, so this enables building | ||
| // a concrete Self value from a numeric literal. | ||
| + From<u8> | ||
| // Permit extending into a `u64`. | ||
| + Into<u64> | ||
| + LowerHex | ||
| + Not<Output=Self> | ||
| + Send | ||
| + Shl<u8, Output=Self> | ||
| + ShlAssign<u8> | ||
| + Shr<u8, Output=Self> | ||
| + ShrAssign<u8> | ||
| // Allow direct access to a concrete implementor type. | ||
| + Sized | ||
| + Sync | ||
| + UpperHex | ||
| { | ||
| /// The width, in bits, of this type. | ||
| const BITS: u8 = size_of::<Self>() as u8 * 8; | ||
| /// The number of bits required to index a bit inside the type. This is | ||
| /// always log<sub>2</sub> of the type’s bit width. | ||
| const INDX: u8 = Self::BITS.trailing_zeros() as u8; | ||
| /// The bitmask to turn an arbitrary number into a bit index. Bit indices | ||
| /// are always stored in the lowest bits of an index value. | ||
| const MASK: u8 = Self::BITS - 1; | ||
| /// Name of the implementing type. This is only necessary until the compiler | ||
| /// stabilizes `type_name()`. | ||
| const TYPENAME: &'static str; | ||
| /// Atomic version of the storage type, to have properly fenced access. | ||
| #[cfg(feature = "atomic")] | ||
| #[doc(hidden)] | ||
| type Atom: Atomic<Self>; | ||
| /// Performs a synchronized load on the underlying element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The element referred to by the `self` reference, loaded synchronously | ||
| /// after any in-progress accesses have concluded. | ||
| #[cfg(feature = "atomic")] | ||
| #[inline(always)] | ||
| fn load(&self) -> Self { | ||
| let aptr = self as *const Self as *const Self::Atom; | ||
| unsafe { &*aptr }.get() | ||
| } | ||
| /// Performs an unsynchronized load on the underlying element. | ||
| /// | ||
| /// As atomic operations are unavailable, this is a standard dereference. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The referent element. | ||
| #[cfg(not(feature = "atomic"))] | ||
| #[inline(always)] | ||
| fn load(&self) -> Self { | ||
| *self | ||
| } | ||
| /// Sets a specific bit in an element to a given value. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit | ||
| /// under this index will be set according to `value`. | ||
| /// - `value`: A Boolean value, which sets the bit on `true` and unsets it | ||
| /// on `false`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `C: Cursor`: A `Cursor` implementation to translate the index into a | ||
| /// position. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example sets and unsets bits in a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::{ | ||
| /// BitStore, | ||
| /// BigEndian, | ||
| /// LittleEndian, | ||
| /// }; | ||
| /// | ||
| /// let mut elt: u16 = 0; | ||
| /// | ||
| /// elt.set::<BigEndian>(1.into(), true); | ||
| /// assert_eq!(elt, 0b0100_0000__0000_0000); | ||
| /// elt.set::<LittleEndian>(1.into(), true); | ||
| /// assert_eq!(elt, 0b0100_0000__0000_0010); | ||
| /// | ||
| /// elt.set::<BigEndian>(1.into(), false); | ||
| /// assert_eq!(elt, 0b0000_0000__0000_0010); | ||
| /// elt.set::<LittleEndian>(1.into(), false); | ||
| /// assert_eq!(elt, 0); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::{BitStore, BigEndian}; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set::<BigEndian>(8.into(), true); | ||
| /// ``` | ||
| #[inline(always)] | ||
| fn set<C>(&mut self, place: BitIdx, value: bool) | ||
| where C: Cursor { | ||
| self.set_at(C::at::<Self>(place), value) | ||
| } | ||
| /// Sets a specific bit in an element to a given value. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit *position* in the element, where `0` is the LSbit and | ||
| /// `Self::MASK` is the MSbit. | ||
| /// - `value`: A Boolean value, which sets the bit high on `true` and unsets | ||
| /// it low on `false`. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example sets and unsets bits in a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::BitStore; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set_at(0.into(), true); | ||
| /// assert_eq!(elt, 0b0000_0001); | ||
| /// elt.set_at(7.into(), true); | ||
| /// assert_eq!(elt, 0b1000_0001); | ||
| /// ``` | ||
| /// | ||
| /// This example overshoots the width, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::BitStore; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set_at(8.into(), true); | ||
| /// ``` | ||
| fn set_at(&mut self, place: BitPos, value: bool) { | ||
| #[cfg(feature = "atomic")] { | ||
| let aptr = self as *const Self as *const Self::Atom; | ||
| if value { | ||
| unsafe { &*aptr }.set(place); | ||
| } | ||
| else { | ||
| unsafe { &*aptr }.clear(place); | ||
| } | ||
| } | ||
| #[cfg(not(feature = "atomic"))] { | ||
| if value { | ||
| *self |= Self::mask_at(place); | ||
| } | ||
| else { | ||
| *self &= !Self::mask_at(place); | ||
| } | ||
| } | ||
| } | ||
| /// Gets a specific bit in an element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit | ||
| /// under this index will be retrieved as a `bool`. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The value of the bit under `place`, as a `bool`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `C: Cursor`: A `Cursor` implementation to translate the index into a | ||
| /// position. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example gets two bits from a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::{BitStore, BigEndian}; | ||
| /// let elt: u8 = 0b0010_0000; | ||
| /// assert!(!elt.get::<BigEndian>(1.into())); | ||
| /// assert!(elt.get::<BigEndian>(2.into())); | ||
| /// assert!(!elt.get::<BigEndian>(3.into())); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::{BitStore, BigEndian}; | ||
| /// 0u8.get::<BigEndian>(8.into()); | ||
| /// ``` | ||
| fn get<C>(&self, place: BitIdx) -> bool | ||
| where C: Cursor { | ||
| self.get_at(C::at::<Self>(place)) | ||
| } | ||
| /// Gets a specific bit in an element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit *position* in the element, from `0` at LSbit to | ||
| /// `Self::MASK` at MSbit. The bit under this position will be retrieved | ||
| /// as a `bool`. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The value of the bit under `place`, as a `bool`. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example gets two bits from a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::BitStore; | ||
| /// let elt: u8 = 0b0010_0000; | ||
| /// assert!(!elt.get_at(4.into())); | ||
| /// assert!(elt.get_at(5.into())); | ||
| /// assert!(!elt.get_at(6.into())); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::BitStore; | ||
| /// 0u8.get_at(8.into()); | ||
| /// ``` | ||
| fn get_at(&self, place: BitPos) -> bool { | ||
| self.load() & Self::mask_at(place) != Self::from(0u8) | ||
| } | ||
| /// Produces the bit mask which selects only the bit at the requested | ||
| /// position. | ||
| /// | ||
| /// This mask must be inverted in order to clear the bit. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: The bit position for which to create a bitmask. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The one-hot encoding of the bit position index. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example produces the one-hot encodings for indices. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::BitStore; | ||
| /// | ||
| /// assert_eq!(u8::mask_at(0.into()), 0b0000_0001); | ||
| /// assert_eq!(u8::mask_at(1.into()), 0b0000_0010); | ||
| /// assert_eq!(u8::mask_at(2.into()), 0b0000_0100); | ||
| /// assert_eq!(u8::mask_at(3.into()), 0b0000_1000); | ||
| /// assert_eq!(u8::mask_at(4.into()), 0b0001_0000); | ||
| /// assert_eq!(u8::mask_at(5.into()), 0b0010_0000); | ||
| /// assert_eq!(u8::mask_at(6.into()), 0b0100_0000); | ||
| /// assert_eq!(u8::mask_at(7.into()), 0b1000_0000); | ||
| /// | ||
| /// assert_eq!(u16::mask_at(8.into()), 0b0000_0001__0000_0000); | ||
| /// assert_eq!(u16::mask_at(9.into()), 0b0000_0010__0000_0000); | ||
| /// assert_eq!(u16::mask_at(10.into()), 0b0000_0100__0000_0000); | ||
| /// assert_eq!(u16::mask_at(11.into()), 0b0000_1000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(12.into()), 0b0001_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(13.into()), 0b0010_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(14.into()), 0b0100_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(15.into()), 0b1000_0000__0000_0000); | ||
| /// | ||
| /// assert_eq!(u32::mask_at(16.into()), 1 << 16); | ||
| /// assert_eq!(u32::mask_at(24.into()), 1 << 24); | ||
| /// assert_eq!(u32::mask_at(31.into()), 1 << 31); | ||
| /// | ||
| /// # #[cfg(target_pointer_width = "64")] { | ||
| /// assert_eq!(u64::mask_at(32.into()), 1 << 32); | ||
| /// assert_eq!(u64::mask_at(48.into()), 1 << 48); | ||
| /// assert_eq!(u64::mask_at(63.into()), 1 << 63); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// These examples ensure that indices panic when out of bounds. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::BitStore; | ||
| /// u8::mask_at(8.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::BitStore; | ||
| /// u16::mask_at(16.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::BitStore; | ||
| /// u32::mask_at(32.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// # #[cfg(target_pointer_width = "64")] { | ||
| /// use bitvec::prelude::BitStore; | ||
| /// u64::mask_at(64.into()); | ||
| /// # } | ||
| /// ``` | ||
| #[inline(always)] | ||
| fn mask_at(place: BitPos) -> Self { | ||
| assert!( | ||
| place.is_valid::<Self>(), | ||
| "Index {} is not a valid position for type {}", | ||
| *place, | ||
| Self::TYPENAME, | ||
| ); | ||
| // Pad 1 to the correct width, then shift up to the correct bit place. | ||
| Self::from(1u8) << *place | ||
| } | ||
| /// Counts how many bits in `self` are set to `1`. | ||
| /// | ||
| /// This zero-extends `self` to `u64`, and uses the [`u64::count_ones`] | ||
| /// inherent method. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The number of bits in `self` set to `1`. This is a `usize` instead of a | ||
| /// `u32` in order to ease arithmetic throughout the crate. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::BitStore; | ||
| /// assert_eq!(BitStore::count_ones(&0u8), 0); | ||
| /// assert_eq!(BitStore::count_ones(&128u8), 1); | ||
| /// assert_eq!(BitStore::count_ones(&192u8), 2); | ||
| /// assert_eq!(BitStore::count_ones(&224u8), 3); | ||
| /// assert_eq!(BitStore::count_ones(&240u8), 4); | ||
| /// assert_eq!(BitStore::count_ones(&248u8), 5); | ||
| /// assert_eq!(BitStore::count_ones(&252u8), 6); | ||
| /// assert_eq!(BitStore::count_ones(&254u8), 7); | ||
| /// assert_eq!(BitStore::count_ones(&255u8), 8); | ||
| /// ``` | ||
| /// | ||
| /// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones | ||
| #[inline(always)] | ||
| fn count_ones(&self) -> usize { | ||
| u64::count_ones((self.load()).into()) as usize | ||
| } | ||
| /// Counts how many bits in `self` are set to `0`. | ||
| /// | ||
| /// This inverts `self`, so all `0` bits are `1` and all `1` bits are `0`, | ||
| /// then zero-extends `self` to `u64` and uses the [`u64::count_ones`] | ||
| /// inherent method. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The number of bits in `self` set to `0`. This is a `usize` instead of a | ||
| /// `u32` in order to ease arithmetic throughout the crate. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::BitStore; | ||
| /// assert_eq!(BitStore::count_zeros(&0u8), 8); | ||
| /// assert_eq!(BitStore::count_zeros(&1u8), 7); | ||
| /// assert_eq!(BitStore::count_zeros(&3u8), 6); | ||
| /// assert_eq!(BitStore::count_zeros(&7u8), 5); | ||
| /// assert_eq!(BitStore::count_zeros(&15u8), 4); | ||
| /// assert_eq!(BitStore::count_zeros(&31u8), 3); | ||
| /// assert_eq!(BitStore::count_zeros(&63u8), 2); | ||
| /// assert_eq!(BitStore::count_zeros(&127u8), 1); | ||
| /// assert_eq!(BitStore::count_zeros(&255u8), 0); | ||
| /// ``` | ||
| /// | ||
| /// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones | ||
| #[inline(always)] | ||
| fn count_zeros(&self) -> usize { | ||
| // invert (0 becomes 1, 1 becomes 0), zero-extend, count ones | ||
| u64::count_ones((!self.load()).into()) as usize | ||
| } | ||
| /// Extends a single bit to fill the entire element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `bit`: The bit to extend. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// An element with all bits set to the input. | ||
| #[inline] | ||
| fn bits(bit: bool) -> Self { | ||
| if bit { | ||
| !Self::from(0) | ||
| } | ||
| else { | ||
| Self::from(0) | ||
| } | ||
| } | ||
| } | ||
| /** Newtype indicating a semantic index into an element. | ||
| This type is consumed by [`Cursor`] implementors, which use it to produce a | ||
| concrete bit position inside an element. | ||
| `BitIdx` is a semantic counter which has a defined, constant, and predictable | ||
| ordering. Values of `BitIdx` refer strictly to abstract ordering, and not to the | ||
| actual position in an element, so `BitIdx(0)` is the first bit in an element, | ||
| but is not required to be the electrical `LSb`, `MSb`, or any other. | ||
| [`Cursor`]: ../cursor/trait.Cursor.html | ||
| **/ | ||
| #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| #[doc(hidden)] | ||
| pub struct BitIdx(pub(crate) u8); | ||
| impl BitIdx { | ||
| /// Checks if the index is valid for a type. | ||
| /// | ||
| /// Indices are valid in the range `0 .. T::BITS`. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The index to validate. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the index is valid for the storage type in question. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type used to determine index validity. | ||
| #[inline] | ||
| pub fn is_valid<T>(self) -> bool | ||
| where T: BitStore { | ||
| *self < T::BITS | ||
| } | ||
| /// Checks if the index is valid as a tail index for a type. | ||
| /// | ||
| /// Tail indices are vaild in the range `1 ..= T::BITS`. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The index to validate as a tail. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the index is valid as a tail for the storage type in question. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage used to determine index tail validity. | ||
| #[inline] | ||
| pub fn is_valid_tail<T>(self) -> bool | ||
| where T: BitStore { | ||
| *self > 0 && *self <= T::BITS | ||
| } | ||
| /// Increments a cursor to the next value, wrapping if needed. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: An incremented cursor. | ||
| /// - `bool`: Marks whether the increment crossed an element boundary. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type for which the increment will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example increments inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(6).incr::<u8>(), (7.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example increments at the high edge, and wraps to the next element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).incr::<u8>(), (0.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| pub fn incr<T>(self) -> (Self, bool) | ||
| where T: BitStore { | ||
| let val = *self; | ||
| assert!( | ||
| self.is_valid::<T>(), | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| let next = val.wrapping_add(1) & T::MASK; | ||
| (next.into(), next == 0) | ||
| } | ||
| /// Increments a tail cursor to the next value, wrapping if needed. | ||
| /// | ||
| /// Tail cursors have the domain `1 ..= T::BITS`, with the exception that | ||
| /// the tail of an empty domain is `0`. As such, it is valid for a tail to | ||
| /// increment *from* `0`, but will never return to it. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original tail cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: An incremented tail cursor. | ||
| /// - `bool`: Marks whether the increment crossed an element boundary | ||
| /// (including from `0` to `1`). | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type for which the increment will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is outside the range `0 ..= T::BITS`, in | ||
| /// order to avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example increments from zero. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(0).incr_tail::<u8>(), (1.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example increments inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).incr_tail::<u8>(), (8.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example increments at the high edge, and wraps to the next element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(8).incr_tail::<u8>(), (1.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| pub fn incr_tail<T>(self) -> (Self, bool) | ||
| where T: BitStore { | ||
| let val = *self; | ||
| // Permit 0 ..= T::BITS, rather than 1 ..= T::BITS, for the empty tail. | ||
| assert!( | ||
| val <= T::BITS, | ||
| "Index out of range: {} exceeds {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| if val == T::BITS { | ||
| (1.into(), true) | ||
| } | ||
| else { | ||
| // Signal wrap if the tail was empty | ||
| (val.wrapping_add(1).into(), val == 0) | ||
| } | ||
| } | ||
| /// Decrements a cursor to the prior value, wrapping if needed. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: A decremented cursor. | ||
| /// - `bool`: Marks whether the decrement crossed an element boundary. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type for which the decrement will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example decrements inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).decr::<u8>(), (0.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example decrements at the low edge, and wraps to the prior element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(0).decr::<u8>(), (7.into(), true)); | ||
| /// # } | ||
| pub fn decr<T>(self) -> (Self, bool) | ||
| where T: BitStore { | ||
| let val = *self; | ||
| assert!( | ||
| self.is_valid::<T>(), | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| let (prev, wrap) = val.overflowing_sub(1); | ||
| ((prev & T::MASK).into(), wrap) | ||
| } | ||
| /// Decrements a tail cursor to the prior value, wrapping if needed. | ||
| /// | ||
| /// Tail cursors have the domain `1 ..= T::BITS`. It is forbidden to | ||
| /// decrement the tail of an empty slice, so this method disallows tails of | ||
| /// value zero. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original tail cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: A decremented tail cursor. | ||
| /// - `bool`: Marks whether the decrement crossed an element boundary (from | ||
| /// `1` to `T::BITS`). | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type for which the decrement will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is outside the range `1 ..= T::BITS`, in | ||
| /// order to avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example demonstrates that the zero tail cannot decrement. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// BitIdx::from(0).decr_tail::<u8>(); | ||
| /// # } | ||
| /// # #[cfg(not(feature = "testing"))] | ||
| /// # panic!("Keeping the test green even when this can't run"); | ||
| /// ``` | ||
| /// | ||
| /// This example decrements inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(2).decr_tail::<u8>(), (1.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example decrements at the low edge, and wraps to the prior element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).decr_tail::<u8>(), (8.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| pub fn decr_tail<T>(self) -> (Self, bool) | ||
| where T: BitStore { | ||
| let val = *self; | ||
| // The empty tail cannot decrement. | ||
| assert!( | ||
| self.is_valid_tail::<T>(), | ||
| "Index out of range: {} departs 1 ..= {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| if val == 1 { | ||
| (T::BITS.into(), true) | ||
| } | ||
| else { | ||
| (val.wrapping_sub(1).into(), false) | ||
| } | ||
| } | ||
| /// Finds the destination bit a certain distance away from a starting bit. | ||
| /// | ||
| /// This produces the number of elements to move, and then the bit index of | ||
| /// the destination bit in the destination element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The bit index in an element of the starting position. This | ||
| /// must be in the domain `0 .. T::BITS`. | ||
| /// - `by`: The number of bits by which to move. Negative values move | ||
| /// downwards in memory: towards `LSb`, then starting again at `MSb` of | ||
| /// the prior element in memory (decreasing address). Positive values move | ||
| /// upwards in memory: towards `MSb`, then starting again at `LSb` of the | ||
| /// subsequent element in memory (increasing address). | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `isize`: The number of elements by which to change the caller’s | ||
| /// element cursor. This value can be passed directly into [`ptr::offset`] | ||
| /// - `BitIdx`: The bit index of the destination bit in the newly selected | ||
| /// element. This will always be in the domain `0 .. T::BITS`. This | ||
| /// value can be passed directly into [`Cursor`] functions to compute the | ||
| /// correct place in the element. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type with which the offset will be calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `from` is not less than `T::BITS`, in order | ||
| /// to avoid index out of range errors. | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// `by` must not be large enough to cause the returned `isize` value to, | ||
| /// when applied to [`ptr::offset`], produce a reference out of bounds of | ||
| /// the original allocation. This method has no means of checking this | ||
| /// requirement. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example calculates offsets within the same element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).offset::<u32>(4isize), (0, 5.into())); | ||
| /// assert_eq!(BitIdx::from(6).offset::<u32>(-3isize), (0, 3.into())); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example calculates offsets that cross into other elements. It uses | ||
| /// `u32`, so the bit index domain is `0 ..= 31`. | ||
| /// | ||
| /// `7 - 18`, modulo 32, wraps down from 0 to 31 and continues decreasing. | ||
| /// `23 + 68`, modulo 32, wraps up from 31 to 0 and continues increasing. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).offset::<u32>(-18isize), (-1, 21.into())); | ||
| /// assert_eq!(BitIdx::from(23).offset::<u32>(68isize), (2, 27.into())); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// [`Cursor`]: ../cursor/trait.Cursor.html | ||
| /// [`ptr::offset`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset | ||
| pub fn offset<T>(self, by: isize) -> (isize, Self) | ||
| where T: BitStore { | ||
| let val = *self; | ||
| assert!( | ||
| val < T::BITS, | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| // If the `isize` addition does not overflow, then the sum can be used | ||
| // directly. | ||
| if let (far, false) = by.overflowing_add(val as isize) { | ||
| // If `far` is in the domain `0 .. T::BITS`, then the offset did | ||
| // not depart the element. | ||
| if far >= 0 && far < T::BITS as isize { | ||
| (0, (far as u8).into()) | ||
| } | ||
| // If `far` is negative, then the offset leaves the initial element | ||
| // going down. If `far` is not less than `T::BITS`, then the | ||
| // offset leaves the initial element going up. | ||
| else { | ||
| (far >> T::INDX, ((far & (T::MASK as isize)) as u8).into()) | ||
| } | ||
| } | ||
| // If the `isize` addition overflows, then the `by` offset is positive. | ||
| // Add as `usize` and use that. This is guaranteed not to overflow, | ||
| // because `isize -> usize` doubles the domain, but `self` is limited | ||
| // to `0 .. T::BITS`. | ||
| else { | ||
| let far = val as usize + by as usize; | ||
| // This addition will always result in a `usize` whose lowest | ||
| // `T::INDX` bits are the bit index in the destination element, | ||
| // and the rest of the high bits (shifted down) are the number of | ||
| // elements by which to advance. | ||
| ( | ||
| (far >> T::INDX) as isize, | ||
| ((far & (T::MASK as usize)) as u8).into(), | ||
| ) | ||
| } | ||
| } | ||
| /// Computes the size of a span from `self` for `len` bits. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self` | ||
| /// - `len`: The number of bits to include in the span. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `usize`: The number of elements `T` included in the span. This will | ||
| /// be in the domain `1 .. usize::max_value()`. | ||
| /// - `BitIdx`: The index of the first bit *after* the span. This will be in | ||
| /// the domain `1 ..= T::BITS`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The type of the elements for which this span is computed. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::{BitIdx, BitStore}; | ||
| /// | ||
| /// let h: BitIdx = 0.into(); | ||
| /// assert_eq!(BitIdx::from(0).span::<u8>(8), (1, 8.into())) | ||
| /// # } | ||
| /// ``` | ||
| pub fn span<T>(self, len: usize) -> (usize, BitIdx) | ||
| where T: BitStore { | ||
| assert!( | ||
| self.is_valid::<T>(), | ||
| "Index {} is invalid for type {}", | ||
| *self, | ||
| T::TYPENAME, | ||
| ); | ||
| // Number of bits in the head *element*. Domain 32 .. 0. | ||
| let bits_in_head = (T::BITS - *self) as usize; | ||
| // If there are `n` bits live between the head cursor (which marks the | ||
| // address of the first live bit) and the back edge of the element, | ||
| // then when `len <= n`, the span covers one element. When `len == n`, | ||
| // the tail will be `T::BITS`, which is valid for a tail. | ||
| if len <= bits_in_head { | ||
| return (1, (*self + len as u8).into()); | ||
| } | ||
| // If there are more bits in the span than `n`, then subtract `n` from | ||
| // `len` and use the difference to count elements and bits. | ||
| // 1 .. | ||
| let bits_after_head = len - bits_in_head; | ||
| // Count the number of wholly filled elements | ||
| let elts = bits_after_head >> T::INDX; | ||
| // Count the number of bits in the *next* element. If this is zero, | ||
| // become `T::BITS`; if it is nonzero, add one more to `elts`. | ||
| // `elts` must have one added to it by default to account for the | ||
| // head element. | ||
| let bits = bits_after_head as u8 & T::MASK; | ||
| /* | ||
| * The expression below this comment is equivalent to the branched | ||
| * structure below, but branchless. | ||
| if bits == 0 { | ||
| (elts + 1, T::BITS.into()) | ||
| } | ||
| else { | ||
| (elts + 2, bits.into()) | ||
| } | ||
| */ | ||
| let tbz = (bits == 0) as u8; | ||
| (elts + 2 - tbz as usize, ((tbz << T::INDX) | bits).into()) | ||
| } | ||
| } | ||
| /// Wraps a `u8` as a `BitIdx`. | ||
| impl From<u8> for BitIdx { | ||
| fn from(src: u8) -> Self { | ||
| BitIdx(src) | ||
| } | ||
| } | ||
| /// Unwraps a `BitIdx` to a `u8`. | ||
| impl Into<u8> for BitIdx { | ||
| fn into(self) -> u8 { | ||
| self.0 | ||
| } | ||
| } | ||
| impl Display for BitIdx { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| Display::fmt(&self.0, f) | ||
| } | ||
| } | ||
| impl Deref for BitIdx { | ||
| type Target = u8; | ||
| fn deref(&self) -> &Self::Target { | ||
| &self.0 | ||
| } | ||
| } | ||
| impl DerefMut for BitIdx { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| &mut self.0 | ||
| } | ||
| } | ||
| /** Newtype indicating a concrete index into an element. | ||
| This type is produced by [`Cursor`] implementors, and denotes a concrete bit in | ||
| an element rather than a semantic bit. | ||
| `Cursor` implementors translate `BitIdx` values, which are semantic places, into | ||
| `BitPos` values, which are concrete electrical positions. | ||
| [`Cursor`]: ../cursor/trait.Cursor.html | ||
| **/ | ||
| #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| #[doc(hidden)] | ||
| pub struct BitPos(pub(crate) u8); | ||
| impl BitPos { | ||
| /// Checks if the position is valid for a type. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The position to validate. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the position is valid for the storage type in question. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: BitStore`: The storage type used to determine position validity. | ||
| pub fn is_valid<T>(self) -> bool | ||
| where T: BitStore { | ||
| *self < T::BITS | ||
| } | ||
| } | ||
| /// Wraps a `u8` as a `BitPos`. | ||
| impl From<u8> for BitPos { | ||
| fn from(src: u8) -> Self { | ||
| BitPos(src) | ||
| } | ||
| } | ||
| /// Unwraps a `BitPos` to a `u8`. | ||
| impl Into<u8> for BitPos { | ||
| fn into(self) -> u8 { | ||
| self.0 | ||
| } | ||
| } | ||
| impl Display for BitPos { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| Display::fmt(&self.0, f) | ||
| } | ||
| } | ||
| impl Deref for BitPos { | ||
| type Target = u8; | ||
| fn deref(&self) -> &Self::Target { | ||
| &self.0 | ||
| } | ||
| } | ||
| impl DerefMut for BitPos { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| &mut self.0 | ||
| } | ||
| } | ||
| impl BitStore for u8 { | ||
| const TYPENAME: &'static str = "u8"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU8; | ||
| } | ||
| impl BitStore for u16 { | ||
| const TYPENAME: &'static str = "u16"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU16; | ||
| } | ||
| impl BitStore for u32 { | ||
| const TYPENAME: &'static str = "u32"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU32; | ||
| } | ||
| #[cfg(target_pointer_width = "64")] | ||
| impl BitStore for u64 { | ||
| const TYPENAME: &'static str = "u64"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU64; | ||
| } | ||
| /// Marker trait to seal `BitStore` against downstream implementation. | ||
| /// | ||
| /// This trait is public in the module, so that other modules in the crate can | ||
| /// use it, but so long as it is not exported by the crate root and this module | ||
| /// is private, this trait effectively forbids downstream implementation of the | ||
| /// `BitStore` trait. | ||
| #[doc(hidden)] | ||
| pub trait Sealed {} | ||
| impl Sealed for u8 {} | ||
| impl Sealed for u16 {} | ||
| impl Sealed for u32 {} | ||
| #[cfg(target_pointer_width = "64")] | ||
| impl Sealed for u64 {} | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| #[test] | ||
| fn jump_far_up() { | ||
| // isize::max_value() is 0x7f...ff, so the result bit will be one less | ||
| // than the start bit. | ||
| for n in 1 .. 8 { | ||
| let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::max_value()); | ||
| assert_eq!(elt, (isize::max_value() >> u8::INDX) + 1); | ||
| assert_eq!(*bit, n - 1); | ||
| } | ||
| let (elt, bit) = BitIdx::from(0).offset::<u8>(isize::max_value()); | ||
| assert_eq!(elt, isize::max_value() >> u8::INDX); | ||
| assert_eq!(*bit, 7); | ||
| } | ||
| #[test] | ||
| fn jump_far_down() { | ||
| // isize::min_value() is 0x80...00, so the result bit will be equal to | ||
| // the start bit | ||
| for n in 0 .. 8 { | ||
| let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::min_value()); | ||
| assert_eq!(elt, isize::min_value() >> u8::INDX); | ||
| assert_eq!(*bit, n); | ||
| } | ||
| } | ||
| #[test] | ||
| #[should_panic] | ||
| fn offset_out_of_bound() { | ||
| BitIdx::from(64).offset::<u64>(isize::max_value()); | ||
| } | ||
| #[test] | ||
| fn incr() { | ||
| assert_eq!(BitIdx(6).incr::<u8>(), (BitIdx(7), false)); | ||
| assert_eq!(BitIdx(7).incr::<u8>(), (BitIdx(0), true)); | ||
| assert_eq!(BitIdx(14).incr::<u16>(), (BitIdx(15), false)); | ||
| assert_eq!(BitIdx(15).incr::<u16>(), (BitIdx(0), true)); | ||
| assert_eq!(BitIdx(30).incr::<u32>(), (BitIdx(31), false)); | ||
| assert_eq!(BitIdx(31).incr::<u32>(), (BitIdx(0), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(62).incr::<u64>(), (BitIdx(63), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(63).incr::<u64>(), (BitIdx(0), true)); | ||
| } | ||
| #[test] | ||
| fn incr_tail() { | ||
| assert_eq!(BitIdx(7).incr_tail::<u8>(), (BitIdx(8), false)); | ||
| assert_eq!(BitIdx(8).incr_tail::<u8>(), (BitIdx(1), true)); | ||
| assert_eq!(BitIdx(15).incr_tail::<u16>(), (BitIdx(16), false)); | ||
| assert_eq!(BitIdx(16).incr_tail::<u16>(), (BitIdx(1), true)); | ||
| assert_eq!(BitIdx(31).incr_tail::<u32>(), (BitIdx(32), false)); | ||
| assert_eq!(BitIdx(32).incr_tail::<u32>(), (BitIdx(1), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(63).incr_tail::<u64>(), (BitIdx(64), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(64).incr_tail::<u64>(), (BitIdx(1), true)); | ||
| } | ||
| #[test] | ||
| fn decr() { | ||
| assert_eq!(BitIdx(1).decr::<u8>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u8>(), (BitIdx(7), true)); | ||
| assert_eq!(BitIdx(1).decr::<u16>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u16>(), (BitIdx(15), true)); | ||
| assert_eq!(BitIdx(1).decr::<u32>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u32>(), (BitIdx(31), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(1).decr::<u64>(), (BitIdx(0), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(0).decr::<u64>(), (BitIdx(63), true)); | ||
| } | ||
| #[test] | ||
| fn decr_tail() { | ||
| assert_eq!(BitIdx(1).decr_tail::<u8>(), (BitIdx(8), true)); | ||
| assert_eq!(BitIdx(8).decr_tail::<u8>(), (BitIdx(7), false)); | ||
| assert_eq!(BitIdx(1).decr_tail::<u16>(), (BitIdx(16), true)); | ||
| assert_eq!(BitIdx(16).decr_tail::<u16>(), (BitIdx(15), false)); | ||
| assert_eq!(BitIdx(1).decr_tail::<u32>(), (BitIdx(32), true)); | ||
| assert_eq!(BitIdx(32).decr_tail::<u32>(), (BitIdx(31), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(1).decr_tail::<u64>(), (BitIdx(64), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(64).decr_tail::<u64>(), (BitIdx(63), false)); | ||
| } | ||
| #[test] | ||
| fn bits() { | ||
| assert_eq!(u8::bits(false), 0); | ||
| assert_eq!(u8::bits(true), u8::max_value()); | ||
| assert_eq!(u16::bits(false), 0); | ||
| assert_eq!(u16::bits(true), u16::max_value()); | ||
| assert_eq!(u32::bits(false), 0); | ||
| assert_eq!(u32::bits(true), u32::max_value()); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(u64::bits(false), 0); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(u64::bits(true), u64::max_value()); | ||
| } | ||
| } |
| { | ||
| "git": { | ||
| "sha1": "ef30c30199d0efc27c891e46838cf5d8265a9f50" | ||
| "sha1": "9843f01a5ac174e9766397ac8f84cc000b9fb0be" | ||
| } | ||
| } |
+1
-1
@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "bitvec" | ||
| version = "0.11.3" | ||
| version = "0.12.0" | ||
| authors = ["myrrlyn <self@myrrlyn.dev>"] | ||
@@ -19,0 +19,0 @@ description = "A crate for manipulating memory, bit by bit" |
+61
-6
@@ -7,8 +7,65 @@ # Changelog | ||
| ## 0.11.3 | ||
| ## 0.12.0 | ||
| [Issue #15]: Incorrect validity check in `BitIdx::span`; excluded tail indices | ||
| which were used in `BitVec::push`, inducing false `panic!` events. Thanks to | ||
| GitHub user [@schomatis] for the report. | ||
| ### Added | ||
| - `BitSlice::at` simulates a write reference to a single bit. It creates an | ||
| instance of `slice::BitGuard`, which holds a mutable reference to the | ||
| requested bit and a `bool` slot. `BitGuard` implements `Deref` and `DerefMut` | ||
| to its local `bool`, and writes its local `bool` value to the specified bit in | ||
| `Drop`. | ||
| This allows writing the following: | ||
| ```rust | ||
| *slice.at(index) = some_bit(); | ||
| ``` | ||
| as equivalent to | ||
| ```rust | ||
| slice.set(index, some_bit()); | ||
| ``` | ||
| Note that binding the value produced by `BitSlice::at` will cause the write to | ||
| occur when that binding *goes out of scope*, not in the assigning statement. | ||
| ```rust | ||
| let slot = slice.at(index); | ||
| *index = some_bit(); | ||
| // write has not yet occurred in `slot` | ||
| // ... more work | ||
| // <- write occurs HERE | ||
| ``` | ||
| In practice, this should not be an issue, since the rules for mutable borrows | ||
| mean that the original slice is not observable until the slot value produced | ||
| by `.at()` goes out of scope. | ||
| - **SEE THE RENAME BELOW.** The `Bits` and `BitsMut` traits provide reference | ||
| conversion from many Rust fundamental types to `BitSlice` regions. `Bits` is | ||
| analagous to `AsRef`, and `BitsMut` to `AsMut`. These traits are implemented | ||
| on the `BitStore` fundamentals, slices of them, and arrays up to 32. | ||
| - `BitSlice::get_unchecked` and `BitSlice::set_unchecked` perform read and write | ||
| actions without any bounds checking to ensure the index is within the slice | ||
| bounds. This allows faster work in tight loops where the index is already | ||
| checked against the slice length. These methods are, of course, incredibly | ||
| unsafe, as they are raw memory access with no safeguards to ensure the read or | ||
| write is within bounds. | ||
| ### Changed | ||
| - `BitVec::retain` changed its function argument from `(bool) -> bool` to | ||
| `(usize, bool) -> bool`, and passes the index as well as the value. | ||
| - `Display` implementations of the `BitIdx` and `BitPos` types now just defer to | ||
| the interior number, and do not write their own type. | ||
| - `BitSlice::as_ptr` and `::as_mut_ptr` now return the null pointer if they are | ||
| the empty slice, rather than a dangling pointer. | ||
| - The trait formerly known as `Bits` in all previous versions is now `BitStore`, | ||
| and the module `bits` is renamed to `store`. Only the `Bits` → `BitStore` | ||
| rename affects public API. | ||
| - Rewrote the README to better describe all the recent work. | ||
| - The documentation examples use the new `as_bitslice` methods instead of the | ||
| much less pleasant `Into` conversions to create `BitSlice` handles. This also | ||
| serves to demonstrate the new favored method to access regions as bit slices. | ||
| ## 0.11.2 | ||
@@ -343,3 +400,2 @@ | ||
| [@ratorx]: https://github.com/ratorx | ||
| [@schomatis]: https://github.com/schomatis | ||
| [@torce]: https://github.com/torce | ||
@@ -351,4 +407,3 @@ [Issue #7]: https://github.com/myrrlyn/bitvec/issues/7 | ||
| [Issue #12]: https://github.com/myrrlyn/bitvec/issues/12 | ||
| [Issue #15]: https://github.com/myrrlyn/bitvec/issues/15 | ||
| [`Sync`]: https://doc.rust-lang.org/stable/core/marker/trait.Sync.html | ||
| [kac]: https://keepachangelog.com/en/1.0.0/ |
+10
-10
@@ -54,11 +54,11 @@ # Atomic Behavior | ||
| The `Bits::set_at` method is the only function in the whole library that writes | ||
| to memory regions. Changing it from | ||
| The `BitStore::set_at` method is the only function in the whole library that | ||
| writes to memory regions. Changing it from | ||
| ```rust,ignore | ||
| ```rust | ||
| if (bit) { | ||
| *self |= 1 << place; | ||
| *self |= 1 << place; | ||
| } | ||
| else { | ||
| *self &= !(1 << place); | ||
| *self &= !(1 << place); | ||
| } | ||
@@ -69,9 +69,9 @@ ``` | ||
| ```rust,ignore | ||
| ```rust | ||
| let aptr: *const Atomic<T> = &self as *const Atomic<T>; | ||
| if (bit) { | ||
| unsafe { &*aptr }.fetch_or(1 << place); | ||
| unsafe { &*aptr }.fetch_or(1 << place); | ||
| } | ||
| else { | ||
| unsafe { &*aptr }.fetch_and(!(1 << place)); | ||
| unsafe { &*aptr }.fetch_and(!(1 << place)); | ||
| } | ||
@@ -86,6 +86,6 @@ ``` | ||
| This required storing the name of the atomic sibling type as an associated type | ||
| in the `Bits` trait, and using `Self::Atom` instead of `Atomic<T>`, though the | ||
| latter would have been a nicer design. | ||
| in the `BitStore` trait, and using `Self::Atom` instead of `Atomic<T>`, though | ||
| the latter would have been a nicer design. | ||
| This is a design document about `bitvec`, not a complaint about the Rust | ||
| standard library, so I will end here. |
+45
-15
| # Bit Patterns | ||
| This document describes how bit slices describe memory, and how their pointer | ||
| structures are composed. | ||
| ## Cursor Addressing | ||
| This table displays the *bit index*, in [base64], of each position in a | ||
@@ -17,3 +22,3 @@ `BitSlice<Cursor, Fundamental>` on a little-endian machine. | ||
| This table displays the bit index in [base64] of each position in a | ||
| This table displays the bit index, in [base64], of each position in a | ||
| `BitSlice<Cursor, Fundamental>` on a big-endian machine. | ||
@@ -93,2 +98,13 @@ | ||
| I personally find this easier to show than to write. The diagram below shows the | ||
| acceptable placements of each value type in a region of sixteen bytes, and the | ||
| number after each `[` glyph is an acceptable modulus for the address. | ||
| > ```text | ||
| > u64 |[0---------------------][8---------------------] | ||
| > u32 |[0---------][4---------][8---------][c---------] | ||
| > u16 |[0---][2---][4---][6---][8---][a---][c---][e---] | ||
| > u8 |[0][1][2][3][4][5][6][7][8][9][a][b][c][d][e][f] | ||
| > ``` | ||
| That means that there is a bit available in the low end of the *pointer* for | ||
@@ -100,6 +116,6 @@ every power of 2 element size above a byte. Narrowing from a byte to a bit still | ||
| > It so happens that pointers on x64 systems only use the low 48 bits of space, | ||
| > and the high 16 bits are unused. Some environments use the empty high bits for | ||
| > data storage, but this is risky as the high bits are considered “not used | ||
| > YET”, and not “available for whatever use”. Also, MMUs tend to trap when those | ||
| > bits are not zero. | ||
| > and the high 16 bits are not used for addressing. Some environments use the | ||
| > empty high bits for data storage, but this is risky as the high bits are | ||
| > considered “not used YET”, and not “available for whatever use”. Also, MMUs | ||
| > tend to trap when these bits are not sign-extensions of bit 47. | ||
| > | ||
@@ -114,3 +130,3 @@ > Also, this trick does not work on 32-bit systems. | ||
| following representation, written in C++ because Rust does not have bitfield | ||
| syntax. | ||
| syntax. The ranges in comments are the range of the field width. | ||
@@ -121,3 +137,3 @@ ```cpp | ||
| size_t ptr_head : __builtin_ctzll(alignof(T)); // 0 ... 3 | ||
| size_t ptr_data : sizeof(T*) * 8 | ||
| size_t ptr_data : sizeof(uintptr_t) * 8 | ||
| - __builtin_ctzll(alignof(T)); // 64/32 ... 61/29 | ||
@@ -141,4 +157,4 @@ | ||
| first *dead* bit *after* the slice ends. | ||
| - the remaining high bits count how many total storage fundamentals are included | ||
| in the bit pointer domain. | ||
| - the remaining high bits index the final *storage fundamental* of the slice, | ||
| counting from the correctly aligned address in the pointer. | ||
@@ -149,3 +165,3 @@ ## Value Patterns | ||
| The null value, `ptr: 0, len: 0` is reserved as an illegal value of `BitPtr<T>` | ||
| The null value, `ptr: 0, len: 0` is reserved as an invalid value of `BitPtr<T>` | ||
| so that it may be used as `Option<BitPtr<T>>::None`. | ||
@@ -155,10 +171,24 @@ | ||
| The empty slices all have *some* pointer value, and fully zeroed other fields. | ||
| The canonical empty slice uses `NonNull::<T>::dangling()` as its pointer value, | ||
| and empty vectors use their allocation address. | ||
| All pointers whose non-`data` members are fully zeroed are considered | ||
| uninhabited. All empty pointers have the same data address, as provided by the | ||
| `NonNull::<T>::dangling()` function. The pointer is marked as `NonNull` in order | ||
| to take advantage of the null-pointer optimization of `Option`. Bit pointers to | ||
| empty space with no backing allocation use the uninhabited address, and bit | ||
| pointers to an allocation with no bits stored use the allocation address. The | ||
| distinction is important for `BitVec`. | ||
| Terminology: I will strive to use *uninhabited* to mean a pointer that does not | ||
| have an associated memory region, and *inhabited* to mean a pointer that does | ||
| have an associated memory region. All *uninhabited* slices **must** be empty; | ||
| *inhabited* slices may be empty or non-empty. | ||
| The region associated with a pointer is not required to be granted by the memory | ||
| allocator, nor managed by the pointer. This information is provided by the | ||
| semantic types atop the pointer; the pointer itself is solely a region | ||
| descriptor. | ||
| ### Inhabited Slices | ||
| For inhabited slices, `elts` contains the offset of the last inhabited element | ||
| in the underlying region. | ||
| For inhabited slices, `elts` contains the offset of the last live element in the | ||
| underlying region. | ||
@@ -165,0 +195,0 @@ A slice with its head and tail in the same element will have an `elts` count of |
@@ -36,4 +36,4 @@ /*! Sieve of Eratosthenes | ||
| use bitvec::prelude::{ | ||
| BitVec, | ||
| BigEndian, | ||
| bitvec, | ||
| }; | ||
@@ -45,3 +45,2 @@ | ||
| env, | ||
| iter, | ||
| }; | ||
@@ -58,5 +57,3 @@ | ||
| let primes = { | ||
| let mut bv = iter::repeat(true) | ||
| .take(max) | ||
| .collect::<BitVec<BigEndian, u64>>(); | ||
| let mut bv = bitvec![BigEndian, u64; 1; max]; | ||
@@ -63,0 +60,0 @@ // 0 and 1 are not primes |
+21
-11
@@ -16,5 +16,7 @@ /*! Demonstrates construction and use of a big-endian, u8, `BitVec` | ||
| bitvec, | ||
| // slice type, analagous to `[u1]` | ||
| BitSlice, | ||
| // trait unifying the primitives (you shouldn’t explicitly need this) | ||
| Bits, | ||
| // primary type of the whole crate! this is where the magic happens | ||
| BitStore, | ||
| // vector type, analagous to `Vec<u1>` | ||
| BitVec, | ||
@@ -79,6 +81,9 @@ // element-traversal trait (you shouldn’t explicitly need this) | ||
| println!("\ | ||
| Notice that `^` did not affect the parts of the tail that were not in | ||
| use, while `!` did affect them. `^` requires a second source, while `!` | ||
| can just flip all elements. `!` is faster, but `^` is less likely to | ||
| break your assumptions about what the memory looks like.\ | ||
| Bit slice operations will never affect or observe memory outside the domain of | ||
| the slice descriptor. This can result in slow behavior when operations must work | ||
| bit-by-bit on partial outer elements, especially as the slice uses more of the | ||
| outer, but any whole elements in the slice will always use the full-element | ||
| operations. This makes `u8` faster than `u32` in cases where the partially-used | ||
| edge elements dominate, but `u32` faster than `u8` when wholly-used elements | ||
| are dominant.\ | ||
| "); | ||
@@ -98,10 +103,15 @@ | ||
| fn render<C: Cursor, T: Bits>(bv: &BitVec<C, T>) { | ||
| println!("Memory information: {} elements, {}", bv.as_slice().len(), bv.len()); | ||
| fn render<C, T>(bs: &BitSlice<C, T>) | ||
| where C: Cursor, T: BitStore { | ||
| println!( | ||
| "Memory information: {} elements, {} bits", | ||
| bs.as_slice().len(), | ||
| bs.len(), | ||
| ); | ||
| println!("Print out the semantic contents"); | ||
| println!("{:#?}", bv); | ||
| println!("{:#?}", bs); | ||
| println!("Print out the memory contents"); | ||
| println!("{:?}", bv.as_slice()); | ||
| println!("{:?}", bs.as_slice()); | ||
| println!("Show the bits in memory"); | ||
| for elt in bv.as_slice() { | ||
| for elt in bs.as_slice() { | ||
| println!("{:0w$b} ", elt, w=std::mem::size_of::<T>() * 8); | ||
@@ -108,0 +118,0 @@ } |
+242
-120
@@ -1,2 +0,2 @@ | ||
| # `BitVec` – Managing memory bit by bit | ||
| # `bitvec` – Managing Memory Bit by Bit | ||
@@ -13,17 +13,18 @@ [![Crate][crate_img]][crate] | ||
| This crate provides data structures which allow working with `bool` as if it | ||
| were truly one bit wide in memory, rather than a `u8` with only two valid | ||
| values. Currently, it only provides `[u1]`, `Box<[u1]>`, and `Vec<u1>` | ||
| structures. | ||
| `bitvec` enables refining memory manipulation from single-byte precision to | ||
| single-bit precision. The bit-precision pointers in this crate allow creation of | ||
| more powerful bit-masks, set arithmetic, and I/O packet processing. | ||
| In addition to compact memory representation, this crate also allows you to | ||
| specify the order in which individual bits are stored in Rust fundamentals, and | ||
| which fundamental element (`u8`, `u16`, `u32`, and on 64-bit systems, `u64`) is | ||
| used to store the bits. | ||
| The core export of this crate is the type `BitSlice`. This type is a region of | ||
| memory with individually-addressable bits. It is accessed by standard Rust | ||
| references: `&BitSlice` and `&mut BitSlice`. These references are able to | ||
| describe and operate on regions that start and end on any arbitrary bit address, | ||
| regardless of alignment to a byte or processor word. | ||
| The data structures provided by this crate track as closely as possible the APIs | ||
| and trait implementations of their proper types in the Rust standard library. | ||
| `BitSlice` corresponds to `[bool]`, `BitBox` to `Box<[bool]>`, and `BitVec` to | ||
| `Vec<bool>`, and each of these types should be drop-in compatible replacements | ||
| for their standard library counterparts. | ||
| Rust provides three types to manipulate a sequence of memory: `&[T]`/`&mut [T]` | ||
| to borrow a region, `Box<[T]>` to statically own a region, and `Vec<T>` to | ||
| dynamically own a region. `bitvec` provides parallel types for each: `&BitSlice` | ||
| and `&mut BitSlice` borrow, `BitBox` statically owns, and `BitVec` dynamically | ||
| owns. These types mirror the relationships and APIs, including inherent methods | ||
| and trait implementations, that are found in the standard library. | ||
@@ -51,3 +52,3 @@ ## What Makes `bitvec` Different Than All The Other Bit Vector Crates | ||
| - You need to directly control a bitstream’s representation in memory. | ||
| - You need to do unpleasant things with communications protocols. | ||
| - You need to do unpleasant things with I/O communications protocols. | ||
| - You need a list of `bool`s that doesn’t waste 7 bits for every bit used. | ||
@@ -61,6 +62,12 @@ - You need to do set arithmetic, or numeric arithmetic, on those lists. | ||
| Your concern with the memory representation of bitsets includes compression. | ||
| `BitSlice` performs absolutely no compression, and maps bits directly into | ||
| memory. Compressed bit sets can be found in other crates, such as the | ||
| [`compacts`] crate, which uses the [Roaring BitSet] format. | ||
| - Your concern with the memory representation of bitsets includes sequence | ||
| compression. `BitSlice` performs absolutely no compression, and maps bits | ||
| directly into memory. Compressed bit sets can be found in other crates, such | ||
| as the [`compacts`] crate, which uses the [Roaring BitSet] format. | ||
| - You want discontiguous data structures, such as a hash table, a tree, or any | ||
| other hallmark of computer science beyond the flat array. `bitvec` does not, | ||
| and will not, accomplish this. You may be able to use `bitvec`’s flat | ||
| structures beneath a type wrapper which handles index processing, but `bitvec` | ||
| types are incapable of accomplishing this task themselves. Also, I don’t know | ||
| how any of those data structures work. | ||
@@ -71,26 +78,18 @@ ## Usage | ||
| I wrote this crate because I was unhappy with the other bit-vector crates | ||
| available. I specifically need to manage raw memory in bit-level precision, and | ||
| this is not a behavior pattern the other bit-vector crates made easily available | ||
| to me. This served as the guiding star for my development process on this crate, | ||
| and remains the crate’s primary goal. | ||
| The `1.34` release of Rust added `const fn` items in the standard library that | ||
| `bitvec` uses for internal work. I am willing to assist you in patching `bitvec` | ||
| to work on an older compiler, but I will not do so in the primary repository. | ||
| To this end, the default type parameters for the `BitVec` type use `u8` as the | ||
| storage primitive and use big-endian ordering of bits: the forwards direction is | ||
| from MSb to LSb, and the backwards direction is from LSb to MSb. | ||
| ### Symbol Import | ||
| To use this crate, you need to depend on it in `Cargo.toml`: | ||
| ```toml | ||
| # Cargo.toml | ||
| [dependencies] | ||
| bitvec = "0.11" | ||
| bitvec = "0.12" | ||
| ``` | ||
| and include it in your crate root `src/main.rs` or `src/lib.rs`: | ||
| `bitvec` is highly modular, and requires several items to function correctly. | ||
| The simplest way to use it is via prelude glob import: | ||
| ```rust,ignore | ||
| // Only if you’re in Rust 2015 | ||
| #[macro_use] | ||
| extern crate bitvec; | ||
| ```rust | ||
| use bitvec::prelude::*; | ||
@@ -101,106 +100,93 @@ ``` | ||
| - `bitvec!` – a macro similar to `vec!`, which allows the creation of `BitVec`s | ||
| of any desired endianness, storage type, and contents. The documentation page | ||
| has a detailed explanation of its syntax. | ||
| - `BigEndian` | ||
| - `BitBox` (only when an allocator is present) | ||
| - `BitSlice` | ||
| - `BitStore` | ||
| - `BitVec` (only when an allocator is present) | ||
| - `Bits` | ||
| - `BitsMut` | ||
| - `Cursor` | ||
| - `LittleEndian` | ||
| - `bitbox!` (only when an allocator is present) | ||
| - `bitvec!` (only when an allocator is present) | ||
| - `BitSlice<C: Cursor, T: Bits>` – the actual bit-slice reference type. It is | ||
| generic over a cursor type (`C`) and storage type (`T`). Note that `BitSlice` | ||
| is unsized, and can never be held directly; it must always be behind a | ||
| reference such as `&BitSlice` or `&mut BitSlice`. | ||
| If you do not want these names imported directly into the local scope – | ||
| `Cursor`, `BigEndian`, and `LittleEndian` are likely culprits for name collision | ||
| – then you can import the prelude with a scope guard: | ||
| Furthermore, it is *impossible* to put `BitSlice` into any kind of intelligent | ||
| pointer such as a `Box` or `Rc`! Any work that involves managing the memory | ||
| behind a bitwise type *must* go through `BitBox` or `BitVec` instead. This may | ||
| change in the future as I learn how to better manage this library, but for now | ||
| this limitation stands. | ||
| ```rust | ||
| use bitvec::prelude as bv; | ||
| ``` | ||
| - `BitBox<C: Cursor, T: Bits>` – a fixed-size bit collection in owned memory. | ||
| and those symbols will all be available only with a `bv::` prefix. | ||
| - `BitVec<C: Cursor, T: Bits>` – the actual bit-vector structure type. It is | ||
| generic over a cursor type (`C`) and storage type (`T`). This type is the main | ||
| worker of the crate. It supports the full `Vec<T>` API and trait | ||
| implementations, with the exception that (at this time) it is impossible to | ||
| take a mutable reference to a single bit. This means that everything except | ||
| for `let elt: &mut bool = &mut bv[index];` and `bv[index] = some_bool();` is | ||
| possible to express. | ||
| ### Cargo Features | ||
| - `Cursor` – an open trait that defines an ordering schema for `BitVec` to use. | ||
| Little and big endian orderings are provided by default. If you wish to | ||
| implement other ordering types, the `Cursor` trait requires one function: | ||
| `bitvec` uses Cargo features to conditionally control some behavior. | ||
| - `fn at<T: Bits>(index: u8) -> u8` takes a semantic index and computes a bit | ||
| offset into the primitive `T` for it. | ||
| The most prominent such behavior is one that cannot be controlled by Cargo | ||
| configuration: `u64` is only usable with this library when targeting a 64-bit | ||
| system. 32-bit system targets are only permitted to use `u8`, `u16`, and `u32`. | ||
| - `BigEndian` – a marker type that implements `Cursor` by defining the forward | ||
| direction as towards LSb and the backward direction as towards MSb. | ||
| #### Atomic Behavior | ||
| - `LittleEndian` – a marker type that implements `Cursor` by defining the | ||
| forward direction as towards MSb and the backward direction as towards LSb. | ||
| `bitvec` uses atomic read/modify/write instructions by default. This is | ||
| necessary to avoid data races in `&mut BitSlice` operations without using | ||
| heavier synchronization mechanisms. If your target does not support Rust’s | ||
| `AtomicU*` types, or you do not want to use atomic RMW instructions, you may | ||
| disable the `atomic` feature: | ||
| - `Bits` – a sealed trait that provides generic access to the four Rust | ||
| primitives usable as storage types: `u8`, `u16`, `u32`, and `u64`. `usize` | ||
| and the signed integers do *not* implement `Bits` and cannot be used as the | ||
| storage type. `u128` also does not implement `Bits`, as I am not confident in | ||
| its memory representation. | ||
| ```toml | ||
| # Cargo.toml | ||
| `BitVec` has the same API as `Vec`, and should be easy to use. | ||
| [dependencies.bitvec] | ||
| default-features = false | ||
| features = [ | ||
| # "atomic", | ||
| "std", | ||
| ] | ||
| ``` | ||
| The `bitvec!` macro can take type information in its first two arguments. | ||
| Because macros do not have access to the type checker, it currently only accepts | ||
| the literal tokens `BigEndian` or `LittleEndian` as the first argument, one of | ||
| the four unsigned integer primitives as the second argument, and then as many | ||
| values as you wish to insert into the collection. It accepts any integer value, | ||
| and maps them to bits by comparing against 0. `0` becomes `false` and any other | ||
| integer, whether it is odd or not, becomes `true`. While the syntax is loose, | ||
| you should only use `0` and `1` to fill the macro, for readability and lack of | ||
| surprise. | ||
| #### Allocator Support | ||
| ### `no_std` | ||
| The two owning structures, `BitBox` and `BitVec`, require the presence of an | ||
| allocator. As `bitvec` is written specifically for use cases where an allocator | ||
| may not exist, this dependence can be disabled. `bitvec` is | ||
| `#![no_std]`-compatible once the `std` feature is disabled. It is not a design | ||
| goal to be `#![no_core]`-compatible. | ||
| This crate can be used in `#![no_std]` libraries, by disabling the default | ||
| feature set. In your `Cargo.toml`, write: | ||
| ```toml | ||
| [dependencies] | ||
| bitvec = { version = "0.11", default-features = false } | ||
| ``` | ||
| # Cargo.toml | ||
| or | ||
| ```toml | ||
| [dependencies.bitvec] | ||
| version = "0.11" | ||
| default-features = false | ||
| features = [ | ||
| "atomic", | ||
| # "std", | ||
| ] | ||
| ``` | ||
| This turns off the standard library imports *and* all usage of dynamic memory | ||
| allocation. Without an allocator, the `bitvec!` and `bitbox!` macros, and the | ||
| `BitVec` and `BitBox` types, are all disabled and removed from the library, | ||
| leaving only the `BitSlice` type. | ||
| If you are working in a `#![no_std]` environment that does have an allocator | ||
| available, you can reënable allocator support with the `alloc` feature: | ||
| To use `bitvec` in a `#![no_std]` environment that *does* have an allocator, | ||
| re-enable the `alloc` feature, like so: | ||
| ```toml | ||
| # Cargo.toml | ||
| ```toml | ||
| [dependencies.bitvec] | ||
| version = "0.11" | ||
| default-features = false | ||
| features = ["alloc"] | ||
| default-features = false # disables "std" | ||
| features = ["alloc"] # enables the allocator | ||
| ``` | ||
| The `alloc` feature restores the owned-memory types and their macros. The only | ||
| difference between `alloc` and `std` is the presence of the standard library | ||
| façade and runtime support. | ||
| This uses `#![feature(alloc)]`, which requires the nightly compiler. | ||
| The `std` feature includes allocation, so using this crate without any feature | ||
| flags *or* by explicitly enabling the `std` feature will enable full | ||
| functionality. | ||
| #### Serde Support | ||
| ### Serde Support | ||
| De/serialization of bit slices is implemented through the `serde` crate. This | ||
| functionality is governed by both the `serde` feature and the `std` feature. | ||
| The `serde` feature, by default, enables serialization for the `BitSlice` type. | ||
| Enabling the `alloc` or `std` features enables both serialization and | ||
| deserialization for the `BitBox` and `BitVec` types. | ||
| By default, when `serde` is enabled, `BitSlice`, `BitBox`, and `BitVec` all gain | ||
| the `Serialize` trait, and `BitBox` and `BitVec` gain the `Deserialize` trait. | ||
| The `serde` feature is opt-in, and requires setting it in your `Cargo.toml`: | ||
| When `std` is disabled, the `BitBox` and `BitVec` types are removed, leaving | ||
| only `BitSlice` with `Serialize`. | ||
@@ -211,12 +197,148 @@ ```toml | ||
| [dependencies.bitvec] | ||
| version = "0.11" | ||
| features = [ | ||
| "serde", # enables serialization | ||
| "std", # enables deserialization | ||
| ] | ||
| features = ["serde"] | ||
| ``` | ||
| ## Example | ||
| ### Data Structures | ||
| `bitvec`’s three data structures are `&BitSlice`, `BitBox`, and `BitVec`. Each | ||
| of these types takes two type parameters, which I have elided previously. | ||
| The first type parameter is the `Cursor` trait. This trait governs how a bit | ||
| index maps to a bit position in the underlying memory. This parameter defaults | ||
| to the `BigEndian` type, which counts from the most significant bit first to the | ||
| least significant bit last. The `LittleEndian` type counts in the opposite | ||
| direction. | ||
| The second type parameter is the `BitStore` trait. This trait abstracts over the | ||
| Rust fundamental types `u8`, `u16`, and `u32`. On 64-bit targets, `u64` is also | ||
| available. This parameter defaults to `u8`, which acts on individual bytes. | ||
| These traits are both explained in the next section. | ||
| `&BitSlice<C: Cursor, T: BitStore>` is an immutable region of memory, | ||
| addressable at bit precision. This has all the inherent methods of Rust’s slice | ||
| primitive, `&[bool]`, and all the trait implementations. It has additional | ||
| methods which are specialized to its status as a slice of individual bits. | ||
| `&mut BitSlice<C: Cursor, T: BitStore>` is a mutable region of memory. This | ||
| functions identically to `&mut [bool]`, with the exception that `IndexMut` is | ||
| impossible: you cannot write `bitslice[index] = bit;`. This restriction is | ||
| sidestepped with the C++-style method `at`: `*bitslice.at(index) = bit;` is the | ||
| shim for write indexing. | ||
| The slice references have no restrictions on the alignment of their start or | ||
| end bits. | ||
| The owning references, described below, will always begin their slice aligned to | ||
| the edge of their `T: BitStore` type parameter. While this is not strictly | ||
| required by the implementation, it is convenient for ensuring that the | ||
| allocation pointer is preserved. | ||
| `BitBox<C: Cursor, T: BitStore>` is a `&mut BitSlice<C: Cursor, T: BitStore>` in | ||
| owned memory. It has few useful methods and no trait implementations of its own. | ||
| It is only capable of taking a bit slice into owned memory. | ||
| `BitVec<C: Cursor, T: BitStore>` is a `BitBox` that can adjust its allocation | ||
| size. It follows the inherent and trait API of the standard library’s `Vec` | ||
| type. | ||
| The API for these types is deliberately uninteresting. They are written to be as | ||
| close to drop-in replacements for the standard library types as possible. The | ||
| end goal of `bitvec` is that you should be able to adopt it by running three | ||
| `sed` find/replace commands on your repository. This is not literally possible, | ||
| but the work required for replacement is intended to be minimal. | ||
| ### Traits | ||
| `bitvec` generalizes its behavior through the use of traits. In order to | ||
| optimize performance, these traits are *not* object-safe, and may *not* be used | ||
| as `dyn Trait` patterns for type erasure. Refactoring `bitvec` to support type | ||
| erasure would require significantly rewriting core infrastructure, and this is | ||
| not a design goal. I am willing to consider it if demand is shown, but I am not | ||
| going to proactively pursue it. | ||
| #### `Cursor` | ||
| The `Cursor` trait is an open-ended trait, that you are free to implement | ||
| yourself. It has one required function: `fn at<T: BitStore>(BitIdx) -> BitPos`. | ||
| This function translates a semantic index to an electrical position. `bitvec` | ||
| provides two implementations for you: `BigEndian` and `LittleEndian`, described | ||
| above. The invariants this function must uphold are listed in its documentation. | ||
| #### `BitStore` | ||
| The `BitStore` trait is sealed, and may only be implemented by this library. It | ||
| is used to abstract over the Rust fundamentals `u8`, `u16`, `u32`, and (on | ||
| 64-bit systems) `u64`. | ||
| Your choice in fundamental types governs how the `Cursor` type translates | ||
| indices, and how the memory underneath your slice is written. The document | ||
| `doc/Bit Patterns.md` enumerates the effect of the `Cursor` and `BitStore` | ||
| combinations on raw memory. | ||
| If you are using `bitvec` to perform set arithmetic, and you expect that your | ||
| sets will have more full elements in the interior than partially-used elements | ||
| on the front and back edge, it is advantageous to use the local CPU word. The | ||
| `BitSlice` operations which traverse the slice are required to perform | ||
| bit-by-bit crawls on partial-use elements, but are able to use whole-word | ||
| instructions on full elements. The latter is a marked acceleration. | ||
| If you are using `bitvec` to perform I/O packet manipulation, you should use the | ||
| fundamental best suited for your protocols. This is likely `u8`, which is why it | ||
| is the default type. | ||
| #### `Bits` and `BitsMut` | ||
| The `Bits` and `BitsMut` traits are entry interfaces to the `BitSlice` types. | ||
| These are equivalent to the `AsRef` and `AsMut` reference conversion traits in | ||
| the standard library, and should be used as such. | ||
| These traits are implemented on the Rust fundamentals that implement `BitStore` | ||
| (`uN`), on slices of those fundamentals (`[uN]`), and the first thirty-two | ||
| arrays of them (`[uN; 0]` to `[uN; 32]`). Each implementation of these traits | ||
| causes a linear expansion of compile time, and going beyond thirty-two both | ||
| surpasses the standard library’s manual implementation limits, and is a | ||
| denial-of-service attack on each rebuild. | ||
| These traits are left open so that if you need to implement them on wider | ||
| arrays, you are able to do so. | ||
| You can use these traits to attach `.as_bitslice::<C: Cursor>()` and | ||
| `.as_mut_bitslice::<C: Cursor>()` conversion methods to any implementor, and | ||
| gain access to a `BitSlice` over that type, or to bound a generic function | ||
| similar to how the standard library uses `AsRef<Path>`: | ||
| ```rust | ||
| let mut base = [0u8; 8]; | ||
| let bits = base.as_mut_bitslice::<LittleEndian>(); | ||
| // bits is now an `&mut BitSlice<LittleEndian, u8>` | ||
| println!("{}", bits.len()); // 64 | ||
| fn operate_on_bits(mut data: impl BitsMut) { | ||
| let bits = data.as_mut_bitslice::<BigEndian>(); | ||
| // `bits` is now an `&mut BitSlice<BigEndian, _>` | ||
| } | ||
| ``` | ||
| ### Macros | ||
| The `bitbox!` and `bitvec!` macros allow convenient production of their | ||
| eponymous types, equivalent to the `vec!` macro in the standard library. | ||
| These macros accept an optional cursor token, an optional type token, and either | ||
| a list of bits or a single bit and a repetition counter. | ||
| Because these are standard macros, not proc-macros, they do not yet produce | ||
| well-optimized expanded code. | ||
| These macros are more thoroughly explained, including a list of all available | ||
| use syntaxes, in their documentation. | ||
| ## Example Usage | ||
| This snippet runs through a selection of library functionality to demonstrate | ||
| behavior. It is deliberately not representative of likely usage. | ||
| ```rust | ||
| extern crate bitvec; | ||
@@ -253,3 +375,3 @@ | ||
| // Set operations | ||
| // Set operations. These deliberately have no effect. | ||
| bv &= repeat(true); | ||
@@ -304,3 +426,3 @@ bv = bv | repeat(false); | ||
| Race conditions are avoided through use of the atomic read/modify/write | ||
| instructions stabilized in `1.34.0`. | ||
| instructions stabilized in `1.34.0`, as described above. | ||
@@ -307,0 +429,0 @@ ## Planned Features |
+17
-17
| /*! Atomic element access | ||
| This module allows the `Bits` trait to access its storage elements as atomic | ||
| This module allows the `BitStore` trait to access its storage elements as atomic | ||
| variants, in order to ensure parallel consistency. | ||
@@ -26,3 +26,3 @@ | ||
| static mut SRC: [u8; 1] = [0]; | ||
| let bs: &mut BitSlice<BigEndian, u8> = (unsafe { &mut SRC as &mut [u8] }).into(); | ||
| let bs = unsafe { SRC.as_mut_bitslice::<BigEndian>() }; | ||
| let (left, right) = bs.split_at_mut(4); | ||
@@ -62,5 +62,5 @@ let l = thread::spawn(move || { | ||
| use crate::bits::{ | ||
| use crate::store::{ | ||
| BitPos, | ||
| Bits, | ||
| BitStore, | ||
| }; | ||
@@ -80,7 +80,7 @@ | ||
| This is not part of the public API; it is an implementation detail of [`Bits`], | ||
| which is public API but is not publicly implementable. | ||
| This is not part of the public API; it is an implementation detail of | ||
| [`BitStore`], which is public API but is not publicly implementable. | ||
| This trait provides three methods, which the `Bits` trait uses to manipulate or | ||
| inspect storage items in a synchronized manner. | ||
| This trait provides three methods, which the `BitStore` trait uses to manipulate | ||
| or inspect storage items in a synchronized manner. | ||
@@ -98,3 +98,3 @@ # Type Parameters | ||
| [`Bits`]: ../bits/trait.Bits.html | ||
| [`BitStore`]: ../bits/trait.BitStore.html | ||
| **/ | ||
@@ -137,3 +137,3 @@ #[cfg_attr(not(feature = "std"), doc = "[`Relaxed`]: https://doc.rust-lang.org/stable/core/sync/atomic/enum.Ordering.html#variant.Relaxed")] | ||
| fn clear(&self, bit: BitPos) { | ||
| self.fetch_and(!<u8 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_and(!<u8 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -143,3 +143,3 @@ | ||
| fn set(&self, bit: BitPos) { | ||
| self.fetch_or(<u8 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_or(<u8 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -156,3 +156,3 @@ | ||
| fn clear(&self, bit: BitPos) { | ||
| self.fetch_and(!<u16 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_and(!<u16 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -162,3 +162,3 @@ | ||
| fn set(&self, bit: BitPos) { | ||
| self.fetch_or(<u16 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_or(<u16 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -175,3 +175,3 @@ | ||
| fn clear(&self, bit: BitPos) { | ||
| self.fetch_and(!<u32 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_and(!<u32 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -181,3 +181,3 @@ | ||
| fn set(&self, bit: BitPos) { | ||
| self.fetch_or(<u32 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_or(<u32 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -195,3 +195,3 @@ | ||
| fn clear(&self, bit: BitPos) { | ||
| self.fetch_and(!<u64 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_and(!<u64 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -201,3 +201,3 @@ | ||
| fn set(&self, bit: BitPos) { | ||
| self.fetch_or(<u64 as Bits>::mask_at(bit), Ordering::Relaxed); | ||
| self.fetch_or(<u64 as BitStore>::mask_at(bit), Ordering::Relaxed); | ||
| } | ||
@@ -204,0 +204,0 @@ |
+153
-1160
@@ -1,434 +0,58 @@ | ||
| /*! Bit management | ||
| /*! Permit use of Rust native types as bit collections. | ||
| The `Bits` trait defines constants and associated functions suitable for | ||
| managing the bit patterns of a fundamental, and is the constraint for the | ||
| storage type of the data structures of the rest of the crate. | ||
| This module exposes two traits, `Bits` and `BitsMut`, which function similarly | ||
| to the `AsRef` and `AsMut` traits in the standard library. These traits allow an | ||
| implementor to express the means by which it can be interpreted as a collection | ||
| of bits. | ||
| The other types in this module provide stronger rules about how indices map to | ||
| concrete bits in fundamental elements. They are implementation details, and are | ||
| not exported in the prelude. | ||
| Trait coherence rules forbid the following blanket implementation, | ||
| ```rust,ignore | ||
| impl<C: Cursor, T: Bits> AsRef<BitSlice<C, T::Store>> for T { | ||
| fn as_ref(&self) -> &BitSlice<C, T::Store> { | ||
| Bits::as_bitslice(self) | ||
| } | ||
| } | ||
| impl<C: Cursor, T: BitsMut> AsMut<BitSlice<C, T::Store>> for T { | ||
| fn as_ref(&mut self) -> &mut BitSlice<C, T::Store> { | ||
| BitsMut::as_mut_bitslice(self) | ||
| } | ||
| } | ||
| ``` | ||
| but it is correct in theory, and so all types which implement `Bits` should | ||
| implement `AsRef<BitSlice>` and all types which implement `BitsMut` should | ||
| implement `AsMut<BitSlice>`. | ||
| !*/ | ||
| use crate::cursor::Cursor; | ||
| use core::{ | ||
| cmp::Eq, | ||
| convert::From, | ||
| fmt::{ | ||
| self, | ||
| Binary, | ||
| Debug, | ||
| Display, | ||
| Formatter, | ||
| LowerHex, | ||
| UpperHex, | ||
| }, | ||
| marker::{ | ||
| Send, | ||
| Sync, | ||
| }, | ||
| mem::size_of, | ||
| ops::{ | ||
| BitAnd, | ||
| BitAndAssign, | ||
| BitOrAssign, | ||
| Deref, | ||
| DerefMut, | ||
| Not, | ||
| Shl, | ||
| ShlAssign, | ||
| Shr, | ||
| ShrAssign, | ||
| }, | ||
| use crate::{ | ||
| cursor::Cursor, | ||
| slice::BitSlice, | ||
| store::BitStore, | ||
| }; | ||
| #[cfg(feature = "atomic")] | ||
| use crate::atomic::Atomic; | ||
| use core::convert::{ | ||
| AsMut, | ||
| AsRef, | ||
| }; | ||
| #[cfg(feature = "atomic")] | ||
| use core::sync::atomic; | ||
| /** Allows a type to be used as a sequence of immutable bits. | ||
| /** Generalizes over the fundamental types for use in `bitvec` data structures. | ||
| # Requirements | ||
| This trait must only be implemented on unsigned integer primitives with full | ||
| alignment. It cannot be implemented on `u128` on any architecture, or on `u64` | ||
| on 32-bit systems. | ||
| The `Sealed` supertrait ensures that this can only be implemented locally, and | ||
| will never be implemented by downstream crates on new types. | ||
| This trait can only be implemented by contiguous structures: individual | ||
| fundamentals, and sequences (arrays or slices) of them. | ||
| **/ | ||
| pub trait Bits: | ||
| // Forbid external implementation | ||
| Sealed | ||
| + Binary | ||
| // Element-wise binary manipulation | ||
| + BitAnd<Self, Output=Self> | ||
| + BitAndAssign<Self> | ||
| + BitOrAssign<Self> | ||
| // Permit indexing into a generic array | ||
| + Copy | ||
| + Debug | ||
| + Display | ||
| // Permit testing a value against 1 in `get()`. | ||
| + Eq | ||
| // Rust treats numeric literals in code as vaguely typed and does not make | ||
| // them concrete until long after trait expansion, so this enables building | ||
| // a concrete Self value from a numeric literal. | ||
| + From<u8> | ||
| // Permit extending into a `u64`. | ||
| + Into<u64> | ||
| + LowerHex | ||
| + Not<Output=Self> | ||
| + Send | ||
| + Shl<u8, Output=Self> | ||
| + ShlAssign<u8> | ||
| + Shr<u8, Output=Self> | ||
| + ShrAssign<u8> | ||
| // Allow direct access to a concrete implementor type. | ||
| + Sized | ||
| + Sync | ||
| + UpperHex | ||
| { | ||
| /// The width, in bits, of this type. | ||
| const BITS: u8 = size_of::<Self>() as u8 * 8; | ||
| pub trait Bits { | ||
| /// The underlying fundamental type of the implementor. | ||
| type Store: BitStore; | ||
| /// The number of bits required to index a bit inside the type. This is | ||
| /// always log<sub>2</sub> of the type’s bit width. | ||
| const INDX: u8 = Self::BITS.trailing_zeros() as u8; | ||
| /// The bitmask to turn an arbitrary number into a bit index. Bit indices | ||
| /// are always stored in the lowest bits of an index value. | ||
| const MASK: u8 = Self::BITS - 1; | ||
| /// Name of the implementing type. This is only necessary until the compiler | ||
| /// stabilizes `type_name()`. | ||
| const TYPENAME: &'static str; | ||
| /// Atomic version of the storage type, to have properly fenced access. | ||
| #[cfg(feature = "atomic")] | ||
| #[doc(hidden)] | ||
| type Atom: Atomic<Self>; | ||
| /// Performs a synchronized load on the underlying element. | ||
| /// Constructs a `BitSlice` reference over data. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The element referred to by the `self` reference, loaded synchronously | ||
| /// after any in-progress accesses have concluded. | ||
| #[cfg(feature = "atomic")] | ||
| #[inline(always)] | ||
| fn load(&self) -> Self { | ||
| let aptr = self as *const Self as *const Self::Atom; | ||
| unsafe { &*aptr }.get() | ||
| } | ||
| /// Performs an unsynchronized load on the underlying element. | ||
| /// | ||
| /// As atomic operations are unavailable, this is a standard dereference. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The referent element. | ||
| #[cfg(not(feature = "atomic"))] | ||
| #[inline(always)] | ||
| fn load(&self) -> Self { | ||
| *self | ||
| } | ||
| /// Sets a specific bit in an element to a given value. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit | ||
| /// under this index will be set according to `value`. | ||
| /// - `value`: A Boolean value, which sets the bit on `true` and unsets it | ||
| /// on `false`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `C: Cursor`: A `Cursor` implementation to translate the index into a | ||
| /// position. | ||
| /// - `C: Cursor`: The `Cursor` type used to index within the slice. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example sets and unsets bits in a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::{ | ||
| /// Bits, | ||
| /// BigEndian, | ||
| /// LittleEndian, | ||
| /// }; | ||
| /// | ||
| /// let mut elt: u16 = 0; | ||
| /// | ||
| /// elt.set::<BigEndian>(1.into(), true); | ||
| /// assert_eq!(elt, 0b0100_0000__0000_0000); | ||
| /// elt.set::<LittleEndian>(1.into(), true); | ||
| /// assert_eq!(elt, 0b0100_0000__0000_0010); | ||
| /// | ||
| /// elt.set::<BigEndian>(1.into(), false); | ||
| /// assert_eq!(elt, 0b0000_0000__0000_0010); | ||
| /// elt.set::<LittleEndian>(1.into(), false); | ||
| /// assert_eq!(elt, 0); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::{Bits, BigEndian}; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set::<BigEndian>(8.into(), true); | ||
| /// ``` | ||
| #[inline(always)] | ||
| fn set<C>(&mut self, place: BitIdx, value: bool) | ||
| where C: Cursor { | ||
| self.set_at(C::at::<Self>(place), value) | ||
| } | ||
| /// Sets a specific bit in an element to a given value. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit *position* in the element, where `0` is the LSbit and | ||
| /// `Self::MASK` is the MSbit. | ||
| /// - `value`: A Boolean value, which sets the bit high on `true` and unsets | ||
| /// it low on `false`. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example sets and unsets bits in a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::Bits; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set_at(0.into(), true); | ||
| /// assert_eq!(elt, 0b0000_0001); | ||
| /// elt.set_at(7.into(), true); | ||
| /// assert_eq!(elt, 0b1000_0001); | ||
| /// ``` | ||
| /// | ||
| /// This example overshoots the width, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::Bits; | ||
| /// let mut elt: u8 = 0; | ||
| /// elt.set_at(8.into(), true); | ||
| /// ``` | ||
| fn set_at(&mut self, place: BitPos, value: bool) { | ||
| #[cfg(feature = "atomic")] { | ||
| let aptr = self as *const Self as *const Self::Atom; | ||
| if value { | ||
| unsafe { &*aptr }.set(place); | ||
| } | ||
| else { | ||
| unsafe { &*aptr }.clear(place); | ||
| } | ||
| } | ||
| #[cfg(not(feature = "atomic"))] { | ||
| if value { | ||
| *self |= Self::mask_at(place); | ||
| } | ||
| else { | ||
| *self &= !Self::mask_at(place); | ||
| } | ||
| } | ||
| } | ||
| /// Gets a specific bit in an element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit | ||
| /// under this index will be retrieved as a `bool`. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The value of the bit under `place`, as a `bool`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `C: Cursor`: A `Cursor` implementation to translate the index into a | ||
| /// position. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example gets two bits from a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::{Bits, BigEndian}; | ||
| /// let elt: u8 = 0b0010_0000; | ||
| /// assert!(!elt.get::<BigEndian>(1.into())); | ||
| /// assert!(elt.get::<BigEndian>(2.into())); | ||
| /// assert!(!elt.get::<BigEndian>(3.into())); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::{Bits, BigEndian}; | ||
| /// 0u8.get::<BigEndian>(8.into()); | ||
| /// ``` | ||
| fn get<C>(&self, place: BitIdx) -> bool | ||
| where C: Cursor { | ||
| self.get_at(C::at::<Self>(place)) | ||
| } | ||
| /// Gets a specific bit in an element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: A bit *position* in the element, from `0` at LSbit to | ||
| /// `Self::MASK` at MSbit. The bit under this position will be retrieved | ||
| /// as a `bool`. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The value of the bit under `place`, as a `bool`. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example gets two bits from a byte. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::Bits; | ||
| /// let elt: u8 = 0b0010_0000; | ||
| /// assert!(!elt.get_at(4.into())); | ||
| /// assert!(elt.get_at(5.into())); | ||
| /// assert!(!elt.get_at(6.into())); | ||
| /// ``` | ||
| /// | ||
| /// This example overruns the index, and panics. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::Bits; | ||
| /// 0u8.get_at(8.into()); | ||
| /// ``` | ||
| fn get_at(&self, place: BitPos) -> bool { | ||
| self.load() & Self::mask_at(place) != Self::from(0u8) | ||
| } | ||
| /// Produces the bit mask which selects only the bit at the requested | ||
| /// position. | ||
| /// | ||
| /// This mask must be inverted in order to clear the bit. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `place`: The bit position for which to create a bitmask. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The one-hot encoding of the bit position index. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `place` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example produces the one-hot encodings for indices. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::Bits; | ||
| /// | ||
| /// assert_eq!(u8::mask_at(0.into()), 0b0000_0001); | ||
| /// assert_eq!(u8::mask_at(1.into()), 0b0000_0010); | ||
| /// assert_eq!(u8::mask_at(2.into()), 0b0000_0100); | ||
| /// assert_eq!(u8::mask_at(3.into()), 0b0000_1000); | ||
| /// assert_eq!(u8::mask_at(4.into()), 0b0001_0000); | ||
| /// assert_eq!(u8::mask_at(5.into()), 0b0010_0000); | ||
| /// assert_eq!(u8::mask_at(6.into()), 0b0100_0000); | ||
| /// assert_eq!(u8::mask_at(7.into()), 0b1000_0000); | ||
| /// | ||
| /// assert_eq!(u16::mask_at(8.into()), 0b0000_0001__0000_0000); | ||
| /// assert_eq!(u16::mask_at(9.into()), 0b0000_0010__0000_0000); | ||
| /// assert_eq!(u16::mask_at(10.into()), 0b0000_0100__0000_0000); | ||
| /// assert_eq!(u16::mask_at(11.into()), 0b0000_1000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(12.into()), 0b0001_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(13.into()), 0b0010_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(14.into()), 0b0100_0000__0000_0000); | ||
| /// assert_eq!(u16::mask_at(15.into()), 0b1000_0000__0000_0000); | ||
| /// | ||
| /// assert_eq!(u32::mask_at(16.into()), 1 << 16); | ||
| /// assert_eq!(u32::mask_at(24.into()), 1 << 24); | ||
| /// assert_eq!(u32::mask_at(31.into()), 1 << 31); | ||
| /// | ||
| /// # #[cfg(target_pointer_width = "64")] { | ||
| /// assert_eq!(u64::mask_at(32.into()), 1 << 32); | ||
| /// assert_eq!(u64::mask_at(48.into()), 1 << 48); | ||
| /// assert_eq!(u64::mask_at(63.into()), 1 << 63); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// These examples ensure that indices panic when out of bounds. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::Bits; | ||
| /// u8::mask_at(8.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::Bits; | ||
| /// u16::mask_at(16.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// use bitvec::prelude::Bits; | ||
| /// u32::mask_at(32.into()); | ||
| /// ``` | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// # #[cfg(target_pointer_width = "64")] { | ||
| /// use bitvec::prelude::Bits; | ||
| /// u64::mask_at(64.into()); | ||
| /// # } | ||
| /// ``` | ||
| #[inline(always)] | ||
| fn mask_at(place: BitPos) -> Self { | ||
| assert!( | ||
| place.is_valid::<Self>(), | ||
| "Index {} is not a valid position for type {}", | ||
| *place, | ||
| Self::TYPENAME, | ||
| ); | ||
| // Pad 1 to the correct width, then shift up to the correct bit place. | ||
| Self::from(1u8) << *place | ||
| } | ||
| /// Counts how many bits in `self` are set to `1`. | ||
| /// | ||
| /// This zero-extends `self` to `u64`, and uses the [`u64::count_ones`] | ||
| /// inherent method. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
@@ -438,4 +62,4 @@ /// | ||
| /// | ||
| /// The number of bits in `self` set to `1`. This is a `usize` instead of a | ||
| /// `u32` in order to ease arithmetic throughout the crate. | ||
| /// A `BitSlice` handle over `self`’s data, using the provided `Cursor` type | ||
| /// and using `Self::Store` as the data type. | ||
| /// | ||
@@ -445,817 +69,186 @@ /// # Examples | ||
| /// ```rust | ||
| /// use bitvec::prelude::Bits; | ||
| /// assert_eq!(Bits::count_ones(&0u8), 0); | ||
| /// assert_eq!(Bits::count_ones(&128u8), 1); | ||
| /// assert_eq!(Bits::count_ones(&192u8), 2); | ||
| /// assert_eq!(Bits::count_ones(&224u8), 3); | ||
| /// assert_eq!(Bits::count_ones(&240u8), 4); | ||
| /// assert_eq!(Bits::count_ones(&248u8), 5); | ||
| /// assert_eq!(Bits::count_ones(&252u8), 6); | ||
| /// assert_eq!(Bits::count_ones(&254u8), 7); | ||
| /// assert_eq!(Bits::count_ones(&255u8), 8); | ||
| /// ``` | ||
| /// use bitvec::prelude::*; | ||
| /// | ||
| /// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones | ||
| #[inline(always)] | ||
| fn count_ones(&self) -> usize { | ||
| u64::count_ones((self.load()).into()) as usize | ||
| } | ||
| /// Counts how many bits in `self` are set to `0`. | ||
| /// | ||
| /// This inverts `self`, so all `0` bits are `1` and all `1` bits are `0`, | ||
| /// then zero-extends `self` to `u64` and uses the [`u64::count_ones`] | ||
| /// inherent method. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `&self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// The number of bits in `self` set to `0`. This is a `usize` instead of a | ||
| /// `u32` in order to ease arithmetic throughout the crate. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::prelude::Bits; | ||
| /// assert_eq!(Bits::count_zeros(&0u8), 8); | ||
| /// assert_eq!(Bits::count_zeros(&1u8), 7); | ||
| /// assert_eq!(Bits::count_zeros(&3u8), 6); | ||
| /// assert_eq!(Bits::count_zeros(&7u8), 5); | ||
| /// assert_eq!(Bits::count_zeros(&15u8), 4); | ||
| /// assert_eq!(Bits::count_zeros(&31u8), 3); | ||
| /// assert_eq!(Bits::count_zeros(&63u8), 2); | ||
| /// assert_eq!(Bits::count_zeros(&127u8), 1); | ||
| /// assert_eq!(Bits::count_zeros(&255u8), 0); | ||
| /// let src = 8u8; | ||
| /// let bits = src.as_bitslice::<BigEndian>(); | ||
| /// assert!(bits[4]); | ||
| /// ``` | ||
| /// | ||
| /// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones | ||
| #[inline(always)] | ||
| fn count_zeros(&self) -> usize { | ||
| // invert (0 becomes 1, 1 becomes 0), zero-extend, count ones | ||
| u64::count_ones((!self.load()).into()) as usize | ||
| } | ||
| /// Extends a single bit to fill the entire element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `bit`: The bit to extend. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// An element with all bits set to the input. | ||
| #[inline] | ||
| fn bits(bit: bool) -> Self { | ||
| // convert 0 to !0 and 1 to 0, then invert. | ||
| !Self::from((bit as u8).wrapping_sub(1)) | ||
| } | ||
| fn as_bitslice<C>(&self) -> &BitSlice<C, Self::Store> | ||
| where C: Cursor; | ||
| } | ||
| /** Newtype indicating a semantic index into an element. | ||
| /** Allows a type to be used as a sequence of mutable bits. | ||
| This type is consumed by [`Cursor`] implementors, which use it to produce a | ||
| concrete bit position inside an element. | ||
| # Requirements | ||
| `BitIdx` is a semantic counter which has a defined, constant, and predictable | ||
| ordering. Values of `BitIdx` refer strictly to abstract ordering, and not to the | ||
| actual position in an element, so `BitIdx(0)` is the first bit in an element, | ||
| but is not required to be the electrical `LSb`, `MSb`, or any other. | ||
| [`Cursor`]: ../cursor/trait.Cursor.html | ||
| This trait can only be implemented by contiguous structures: individual | ||
| fundamentals, and sequences (arrays or slices) of them. | ||
| **/ | ||
| #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| #[doc(hidden)] | ||
| pub struct BitIdx(pub(crate) u8); | ||
| impl BitIdx { | ||
| /// Checks if the index is valid for a type. | ||
| pub trait BitsMut: Bits { | ||
| /// Constructs a mutable `BitSlice` reference over data. | ||
| /// | ||
| /// Indices are valid in the range `0 .. T::BITS`. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The index to validate. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the index is valid for the storage type in question. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type used to determine index validity. | ||
| #[inline] | ||
| pub fn is_valid<T>(self) -> bool | ||
| where T: Bits { | ||
| *self < T::BITS | ||
| } | ||
| /// Checks if the index is valid as a tail index for a type. | ||
| /// - `C: Cursor`: The `Cursor` type used to index within the slice. | ||
| /// | ||
| /// Tail indices are vaild in the range `1 ..= T::BITS`. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The index to validate as a tail. | ||
| /// - `&mut self` | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the index is valid as a tail for the storage type in question. | ||
| /// A `BitSlice` handle over `self`’s data, using the provided `Cursor` type | ||
| /// and using `Self::Store` as the data type. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage used to determine index tail validity. | ||
| #[inline] | ||
| pub fn is_valid_tail<T>(self) -> bool | ||
| where T: Bits { | ||
| *self > 0 && *self <= T::BITS | ||
| } | ||
| /// Increments a cursor to the next value, wrapping if needed. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: An incremented cursor. | ||
| /// - `bool`: Marks whether the increment crossed an element boundary. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type for which the increment will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example increments inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(6).incr::<u8>(), (7.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// use bitvec::prelude::*; | ||
| /// | ||
| /// This example increments at the high edge, and wraps to the next element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).incr::<u8>(), (0.into(), true)); | ||
| /// # } | ||
| /// let mut src = 8u8; | ||
| /// let bits = src.as_mut_bitslice::<LittleEndian>(); | ||
| /// assert!(bits[3]); | ||
| /// *bits.at(3) = false; | ||
| /// assert!(!bits[3]); | ||
| /// ``` | ||
| pub fn incr<T>(self) -> (Self, bool) | ||
| where T: Bits { | ||
| let val = *self; | ||
| assert!( | ||
| self.is_valid::<T>(), | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| let next = val.wrapping_add(1) & T::MASK; | ||
| (next.into(), next == 0) | ||
| } | ||
| fn as_mut_bitslice<C>(&mut self) -> &mut BitSlice<C, Self::Store> | ||
| where C: Cursor; | ||
| } | ||
| /// Increments a tail cursor to the next value, wrapping if needed. | ||
| /// | ||
| /// Tail cursors have the domain `1 ..= T::BITS`, with the exception that | ||
| /// the tail of an empty domain is `0`. As such, it is valid for a tail to | ||
| /// increment *from* `0`, but will never return to it. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original tail cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: An incremented tail cursor. | ||
| /// - `bool`: Marks whether the increment crossed an element boundary | ||
| /// (including from `0` to `1`). | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type for which the increment will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is outside the range `0 ..= T::BITS`, in | ||
| /// order to avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example increments from zero. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(0).incr_tail::<u8>(), (1.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example increments inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).incr_tail::<u8>(), (8.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example increments at the high edge, and wraps to the next element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(8).incr_tail::<u8>(), (1.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| pub fn incr_tail<T>(self) -> (Self, bool) | ||
| where T: Bits { | ||
| let val = *self; | ||
| // Permit 0 ..= T::BITS, rather than 1 ..= T::BITS, for the empty tail. | ||
| assert!( | ||
| val <= T::BITS, | ||
| "Index out of range: {} exceeds {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| if val == T::BITS { | ||
| (1.into(), true) | ||
| } | ||
| else { | ||
| // Signal wrap if the tail was empty | ||
| (val.wrapping_add(1).into(), val == 0) | ||
| } | ||
| macro_rules! impl_bits_for { | ||
| ( $( $t:ty ),* ) => { $( | ||
| impl<C> AsMut<BitSlice<C, $t>> for $t | ||
| where C: Cursor { | ||
| fn as_mut(&mut self) -> &mut BitSlice<C, $t> { | ||
| BitsMut::as_mut_bitslice(self) | ||
| } | ||
| } | ||
| /// Decrements a cursor to the prior value, wrapping if needed. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: A decremented cursor. | ||
| /// - `bool`: Marks whether the decrement crossed an element boundary. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type for which the decrement will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is not less than `T::BITS`, in order to | ||
| /// avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example decrements inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).decr::<u8>(), (0.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example decrements at the low edge, and wraps to the prior element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(0).decr::<u8>(), (7.into(), true)); | ||
| /// # } | ||
| pub fn decr<T>(self) -> (Self, bool) | ||
| where T: Bits { | ||
| let val = *self; | ||
| assert!( | ||
| self.is_valid::<T>(), | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| let (prev, wrap) = val.overflowing_sub(1); | ||
| ((prev & T::MASK).into(), wrap) | ||
| impl<C> AsRef<BitSlice<C, $t>> for $t | ||
| where C: Cursor { | ||
| fn as_ref(&self) -> &BitSlice<C, $t> { | ||
| Bits::as_bitslice(self) | ||
| } | ||
| } | ||
| /// Decrements a tail cursor to the prior value, wrapping if needed. | ||
| /// | ||
| /// Tail cursors have the domain `1 ..= T::BITS`. It is forbidden to | ||
| /// decrement the tail of an empty slice, so this method disallows tails of | ||
| /// value zero. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The original tail cursor. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `Self`: A decremented tail cursor. | ||
| /// - `bool`: Marks whether the decrement crossed an element boundary (from | ||
| /// `1` to `T::BITS`). | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type for which the decrement will be | ||
| /// calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This method panics if `self` is outside the range `1 ..= T::BITS`, in | ||
| /// order to avoid index out of range errors. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example demonstrates that the zero tail cannot decrement. | ||
| /// | ||
| /// ```rust,should_panic | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// BitIdx::from(0).decr_tail::<u8>(); | ||
| /// # } | ||
| /// # #[cfg(not(feature = "testing"))] | ||
| /// # panic!("Keeping the test green even when this can't run"); | ||
| /// ``` | ||
| /// | ||
| /// This example decrements inside an element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(2).decr_tail::<u8>(), (1.into(), false)); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example decrements at the low edge, and wraps to the prior element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).decr_tail::<u8>(), (8.into(), true)); | ||
| /// # } | ||
| /// ``` | ||
| pub fn decr_tail<T>(self) -> (Self, bool) | ||
| where T: Bits { | ||
| let val = *self; | ||
| // The empty tail cannot decrement. | ||
| assert!( | ||
| self.is_valid_tail::<T>(), | ||
| "Index out of range: {} departs 1 ..= {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| if val == 1 { | ||
| (T::BITS.into(), true) | ||
| } | ||
| else { | ||
| (val.wrapping_sub(1).into(), false) | ||
| } | ||
| } | ||
| impl Bits for $t { | ||
| type Store = $t; | ||
| /// Finds the destination bit a certain distance away from a starting bit. | ||
| /// | ||
| /// This produces the number of elements to move, and then the bit index of | ||
| /// the destination bit in the destination element. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The bit index in an element of the starting position. This | ||
| /// must be in the domain `0 .. T::BITS`. | ||
| /// - `by`: The number of bits by which to move. Negative values move | ||
| /// downwards in memory: towards `LSb`, then starting again at `MSb` of | ||
| /// the prior element in memory (decreasing address). Positive values move | ||
| /// upwards in memory: towards `MSb`, then starting again at `LSb` of the | ||
| /// subsequent element in memory (increasing address). | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `isize`: The number of elements by which to change the caller’s | ||
| /// element cursor. This value can be passed directly into [`ptr::offset`] | ||
| /// - `BitIdx`: The bit index of the destination bit in the newly selected | ||
| /// element. This will always be in the domain `0 .. T::BITS`. This | ||
| /// value can be passed directly into [`Cursor`] functions to compute the | ||
| /// correct place in the element. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type with which the offset will be calculated. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// This function panics if `from` is not less than `T::BITS`, in order | ||
| /// to avoid index out of range errors. | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// `by` must not be large enough to cause the returned `isize` value to, | ||
| /// when applied to [`ptr::offset`], produce a reference out of bounds of | ||
| /// the original allocation. This method has no means of checking this | ||
| /// requirement. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example calculates offsets within the same element. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(1).offset::<u32>(4isize), (0, 5.into())); | ||
| /// assert_eq!(BitIdx::from(6).offset::<u32>(-3isize), (0, 3.into())); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// This example calculates offsets that cross into other elements. It uses | ||
| /// `u32`, so the bit index domain is `0 ..= 31`. | ||
| /// | ||
| /// `7 - 18`, modulo 32, wraps down from 0 to 31 and continues decreasing. | ||
| /// `23 + 68`, modulo 32, wraps up from 31 to 0 and continues increasing. | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::BitIdx; | ||
| /// assert_eq!(BitIdx::from(7).offset::<u32>(-18isize), (-1, 21.into())); | ||
| /// assert_eq!(BitIdx::from(23).offset::<u32>(68isize), (2, 27.into())); | ||
| /// # } | ||
| /// ``` | ||
| /// | ||
| /// [`Cursor`]: ../cursor/trait.Cursor.html | ||
| /// [`ptr::offset`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset | ||
| pub fn offset<T>(self, by: isize) -> (isize, Self) | ||
| where T: Bits { | ||
| let val = *self; | ||
| assert!( | ||
| val < T::BITS, | ||
| "Index out of range: {} overflows {}", | ||
| val, | ||
| T::BITS, | ||
| ); | ||
| // If the `isize` addition does not overflow, then the sum can be used | ||
| // directly. | ||
| if let (far, false) = by.overflowing_add(val as isize) { | ||
| // If `far` is in the domain `0 .. T::BITS`, then the offset did | ||
| // not depart the element. | ||
| if far >= 0 && far < T::BITS as isize { | ||
| (0, (far as u8).into()) | ||
| } | ||
| // If `far` is negative, then the offset leaves the initial element | ||
| // going down. If `far` is not less than `T::BITS`, then the | ||
| // offset leaves the initial element going up. | ||
| else { | ||
| (far >> T::INDX, ((far & (T::MASK as isize)) as u8).into()) | ||
| } | ||
| } | ||
| // If the `isize` addition overflows, then the `by` offset is positive. | ||
| // Add as `usize` and use that. This is guaranteed not to overflow, | ||
| // because `isize -> usize` doubles the domain, but `self` is limited | ||
| // to `0 .. T::BITS`. | ||
| else { | ||
| let far = val as usize + by as usize; | ||
| // This addition will always result in a `usize` whose lowest | ||
| // `T::INDX` bits are the bit index in the destination element, | ||
| // and the rest of the high bits (shifted down) are the number of | ||
| // elements by which to advance. | ||
| ( | ||
| (far >> T::INDX) as isize, | ||
| ((far & (T::MASK as usize)) as u8).into(), | ||
| ) | ||
| } | ||
| fn as_bitslice<C>(&self) -> &BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_element(self) | ||
| } | ||
| /// Computes the size of a span from `self` for `len` bits. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self` | ||
| /// - `len`: The number of bits to include in the span. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// - `usize`: The number of elements `T` included in the span. This will | ||
| /// be in the domain `1 .. usize::max_value()`. | ||
| /// - `BitIdx`: The index of the first bit *after* the span. This will be in | ||
| /// the domain `1 ..= T::BITS`. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The type of the elements for which this span is computed. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// # #[cfg(feature = "testing")] { | ||
| /// use bitvec::testing::{BitIdx, Bits}; | ||
| /// | ||
| /// let h: BitIdx = 0.into(); | ||
| /// assert_eq!(BitIdx::from(0).span::<u8>(8), (1, 8.into())) | ||
| /// # } | ||
| /// ``` | ||
| pub fn span<T>(self, len: usize) -> (usize, BitIdx) | ||
| where T: Bits { | ||
| assert!( | ||
| *self <= T::BITS, | ||
| "Index {} is invalid for type {}", | ||
| *self, | ||
| T::TYPENAME, | ||
| ); | ||
| // Number of bits in the head *element*. Domain 32 .. 0. | ||
| let bits_in_head = (T::BITS - *self) as usize; | ||
| // If there are `n` bits live between the head cursor (which marks the | ||
| // address of the first live bit) and the back edge of the element, | ||
| // then when `len <= n`, the span covers one element. When `len == n`, | ||
| // the tail will be `T::BITS`, which is valid for a tail. | ||
| if len <= bits_in_head { | ||
| return (1, (*self + len as u8).into()); | ||
| } | ||
| // If there are more bits in the span than `n`, then subtract `n` from | ||
| // `len` and use the difference to count elements and bits. | ||
| // 1 .. | ||
| let bits_after_head = len - bits_in_head; | ||
| // Count the number of wholly filled elements | ||
| let elts = bits_after_head >> T::INDX; | ||
| // Count the number of bits in the *next* element. If this is zero, | ||
| // become `T::BITS`; if it is nonzero, add one more to `elts`. | ||
| // `elts` must have one added to it by default to account for the | ||
| // head element. | ||
| let bits = bits_after_head as u8 & T::MASK; | ||
| /* | ||
| * The expression below this comment is equivalent to the branched | ||
| * structure below, but branchless. | ||
| if bits == 0 { | ||
| (elts + 1, T::BITS.into()) | ||
| } | ||
| else { | ||
| (elts + 2, bits.into()) | ||
| } | ||
| */ | ||
| let tbz = (bits == 0) as u8; | ||
| (elts + 2 - tbz as usize, ((tbz << T::INDX) | bits).into()) | ||
| } | ||
| } | ||
| /// Wraps a `u8` as a `BitIdx`. | ||
| impl From<u8> for BitIdx { | ||
| fn from(src: u8) -> Self { | ||
| BitIdx(src) | ||
| impl BitsMut for $t { | ||
| fn as_mut_bitslice<C>(&mut self) -> &mut BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_element_mut(self) | ||
| } | ||
| } | ||
| /// Unwraps a `BitIdx` to a `u8`. | ||
| impl Into<u8> for BitIdx { | ||
| fn into(self) -> u8 { | ||
| self.0 | ||
| impl<C> AsMut<BitSlice<C, $t>> for [$t] | ||
| where C: Cursor { | ||
| fn as_mut(&mut self) -> &mut BitSlice<C, $t> { | ||
| BitsMut::as_mut_bitslice(self) | ||
| } | ||
| } | ||
| impl Display for BitIdx { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| write!(f, "BitIdx({})", self.0) | ||
| impl<C> AsRef<BitSlice<C, $t>> for [$t] | ||
| where C: Cursor { | ||
| fn as_ref(&self) -> &BitSlice<C, $t> { | ||
| Bits::as_bitslice(self) | ||
| } | ||
| } | ||
| impl Deref for BitIdx { | ||
| type Target = u8; | ||
| impl Bits for [$t] { | ||
| type Store = $t; | ||
| fn deref(&self) -> &Self::Target { | ||
| &self.0 | ||
| fn as_bitslice<C>(&self) -> &BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_slice(self) | ||
| } | ||
| } | ||
| impl DerefMut for BitIdx { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| &mut self.0 | ||
| impl BitsMut for [$t] { | ||
| fn as_mut_bitslice<C>(&mut self) -> &mut BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_slice_mut(self) | ||
| } | ||
| } | ||
| /** Newtype indicating a concrete index into an element. | ||
| This type is produced by [`Cursor`] implementors, and denotes a concrete bit in | ||
| an element rather than a semantic bit. | ||
| `Cursor` implementors translate `BitIdx` values, which are semantic places, into | ||
| `BitPos` values, which are concrete electrical positions. | ||
| [`Cursor`]: ../cursor/trait.Cursor.html | ||
| **/ | ||
| #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| #[doc(hidden)] | ||
| pub struct BitPos(pub(crate) u8); | ||
| impl BitPos { | ||
| /// Checks if the position is valid for a type. | ||
| /// | ||
| /// # Parameters | ||
| /// | ||
| /// - `self`: The position to validate. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// Whether the position is valid for the storage type in question. | ||
| /// | ||
| /// # Type Parameters | ||
| /// | ||
| /// - `T: Bits`: The storage type used to determine position validity. | ||
| pub fn is_valid<T>(self) -> bool | ||
| where T: Bits { | ||
| *self < T::BITS | ||
| impl<C> AsMut<BitSlice<C, $t>> for [$t; 0] | ||
| where C: Cursor { | ||
| fn as_mut(&mut self) -> &mut BitSlice<C, $t> { | ||
| BitsMut::as_mut_bitslice(self) | ||
| } | ||
| } | ||
| /// Wraps a `u8` as a `BitPos`. | ||
| impl From<u8> for BitPos { | ||
| fn from(src: u8) -> Self { | ||
| BitPos(src) | ||
| impl<C> AsRef<BitSlice<C, $t>> for [$t; 0] | ||
| where C: Cursor { | ||
| fn as_ref(&self) -> &BitSlice<C, $t> { | ||
| Bits::as_bitslice(self) | ||
| } | ||
| } | ||
| /// Unwraps a `BitPos` to a `u8`. | ||
| impl Into<u8> for BitPos { | ||
| fn into(self) -> u8 { | ||
| self.0 | ||
| impl Bits for [$t; 0] { | ||
| type Store = $t; | ||
| fn as_bitslice<C>(&self) -> &BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::empty() | ||
| } | ||
| } | ||
| impl Display for BitPos { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| write!(f, "BitPos({})", self.0) | ||
| impl BitsMut for [$t; 0] { | ||
| fn as_mut_bitslice<C>(&mut self) -> &mut BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::empty_mut() | ||
| } | ||
| } | ||
| impl Deref for BitPos { | ||
| type Target = u8; | ||
| impl_bits_for! { array $t ; | ||
| 1 2 3 4 5 6 7 8 9 | ||
| 10 11 12 13 14 15 16 17 18 19 | ||
| 20 21 22 23 24 25 26 27 28 29 | ||
| 30 31 32 // going above 32 is a DoS attack on the compiler | ||
| } | ||
| )* }; | ||
| fn deref(&self) -> &Self::Target { | ||
| &self.0 | ||
| ( array $t:ty ; $( $n:expr )* ) => { $( | ||
| impl<C> AsMut<BitSlice<C, $t>> for [$t; $n] | ||
| where C: Cursor { | ||
| fn as_mut(&mut self) -> &mut BitSlice<C, $t> { | ||
| BitsMut::as_mut_bitslice(self) | ||
| } | ||
| } | ||
| impl DerefMut for BitPos { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| &mut self.0 | ||
| impl<C> AsRef<BitSlice<C, $t>> for [$t; $n] | ||
| where C: Cursor { | ||
| fn as_ref(&self) -> &BitSlice<C, $t> { | ||
| Bits::as_bitslice(self) | ||
| } | ||
| } | ||
| impl Bits for u8 { | ||
| const TYPENAME: &'static str = "u8"; | ||
| impl Bits for [$t; $n] { | ||
| type Store = $t; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU8; | ||
| fn as_bitslice<C>(&self) -> &BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_slice(&self[..]) | ||
| } | ||
| } | ||
| impl Bits for u16 { | ||
| const TYPENAME: &'static str = "u16"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU16; | ||
| impl BitsMut for [$t; $n] { | ||
| fn as_mut_bitslice<C>(&mut self) -> &mut BitSlice<C, Self::Store> | ||
| where C: Cursor { | ||
| BitSlice::from_slice_mut(&mut self[..]) | ||
| } | ||
| } | ||
| impl Bits for u32 { | ||
| const TYPENAME: &'static str = "u32"; | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU32; | ||
| )* }; | ||
| } | ||
| #[cfg(target_pointer_width = "64")] | ||
| impl Bits for u64 { | ||
| const TYPENAME: &'static str = "u64"; | ||
| impl_bits_for! { u8, u16, u32 } | ||
| #[cfg(feature = "atomic")] | ||
| type Atom = atomic::AtomicU64; | ||
| } | ||
| /// Marker trait to seal `Bits` against downstream implementation. | ||
| /// | ||
| /// This trait is public in the module, so that other modules in the crate can | ||
| /// use it, but so long as it is not exported by the crate root and this module | ||
| /// is private, this trait effectively forbids downstream implementation of the | ||
| /// `Bits` trait. | ||
| #[doc(hidden)] | ||
| pub trait Sealed {} | ||
| impl Sealed for u8 {} | ||
| impl Sealed for u16 {} | ||
| impl Sealed for u32 {} | ||
| #[cfg(target_pointer_width = "64")] | ||
| impl Sealed for u64 {} | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| #[test] | ||
| fn jump_far_up() { | ||
| // isize::max_value() is 0x7f...ff, so the result bit will be one less | ||
| // than the start bit. | ||
| for n in 1 .. 8 { | ||
| let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::max_value()); | ||
| assert_eq!(elt, (isize::max_value() >> u8::INDX) + 1); | ||
| assert_eq!(*bit, n - 1); | ||
| } | ||
| let (elt, bit) = BitIdx::from(0).offset::<u8>(isize::max_value()); | ||
| assert_eq!(elt, isize::max_value() >> u8::INDX); | ||
| assert_eq!(*bit, 7); | ||
| } | ||
| #[test] | ||
| fn jump_far_down() { | ||
| // isize::min_value() is 0x80...00, so the result bit will be equal to | ||
| // the start bit | ||
| for n in 0 .. 8 { | ||
| let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::min_value()); | ||
| assert_eq!(elt, isize::min_value() >> u8::INDX); | ||
| assert_eq!(*bit, n); | ||
| } | ||
| } | ||
| #[test] | ||
| #[should_panic] | ||
| fn offset_out_of_bound() { | ||
| BitIdx::from(64).offset::<u64>(isize::max_value()); | ||
| } | ||
| #[test] | ||
| fn incr() { | ||
| assert_eq!(BitIdx(6).incr::<u8>(), (BitIdx(7), false)); | ||
| assert_eq!(BitIdx(7).incr::<u8>(), (BitIdx(0), true)); | ||
| assert_eq!(BitIdx(14).incr::<u16>(), (BitIdx(15), false)); | ||
| assert_eq!(BitIdx(15).incr::<u16>(), (BitIdx(0), true)); | ||
| assert_eq!(BitIdx(30).incr::<u32>(), (BitIdx(31), false)); | ||
| assert_eq!(BitIdx(31).incr::<u32>(), (BitIdx(0), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(62).incr::<u64>(), (BitIdx(63), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(63).incr::<u64>(), (BitIdx(0), true)); | ||
| } | ||
| #[test] | ||
| fn incr_tail() { | ||
| assert_eq!(BitIdx(7).incr_tail::<u8>(), (BitIdx(8), false)); | ||
| assert_eq!(BitIdx(8).incr_tail::<u8>(), (BitIdx(1), true)); | ||
| assert_eq!(BitIdx(15).incr_tail::<u16>(), (BitIdx(16), false)); | ||
| assert_eq!(BitIdx(16).incr_tail::<u16>(), (BitIdx(1), true)); | ||
| assert_eq!(BitIdx(31).incr_tail::<u32>(), (BitIdx(32), false)); | ||
| assert_eq!(BitIdx(32).incr_tail::<u32>(), (BitIdx(1), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(63).incr_tail::<u64>(), (BitIdx(64), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(64).incr_tail::<u64>(), (BitIdx(1), true)); | ||
| } | ||
| #[test] | ||
| fn decr() { | ||
| assert_eq!(BitIdx(1).decr::<u8>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u8>(), (BitIdx(7), true)); | ||
| assert_eq!(BitIdx(1).decr::<u16>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u16>(), (BitIdx(15), true)); | ||
| assert_eq!(BitIdx(1).decr::<u32>(), (BitIdx(0), false)); | ||
| assert_eq!(BitIdx(0).decr::<u32>(), (BitIdx(31), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(1).decr::<u64>(), (BitIdx(0), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(0).decr::<u64>(), (BitIdx(63), true)); | ||
| } | ||
| #[test] | ||
| fn decr_tail() { | ||
| assert_eq!(BitIdx(1).decr_tail::<u8>(), (BitIdx(8), true)); | ||
| assert_eq!(BitIdx(8).decr_tail::<u8>(), (BitIdx(7), false)); | ||
| assert_eq!(BitIdx(1).decr_tail::<u16>(), (BitIdx(16), true)); | ||
| assert_eq!(BitIdx(16).decr_tail::<u16>(), (BitIdx(15), false)); | ||
| assert_eq!(BitIdx(1).decr_tail::<u32>(), (BitIdx(32), true)); | ||
| assert_eq!(BitIdx(32).decr_tail::<u32>(), (BitIdx(31), false)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(1).decr_tail::<u64>(), (BitIdx(64), true)); | ||
| #[cfg(target_pointer_width = "64")] | ||
| assert_eq!(BitIdx(64).decr_tail::<u64>(), (BitIdx(63), false)); | ||
| } | ||
| } | ||
| impl_bits_for! { u64 } |
+125
-122
@@ -10,3 +10,2 @@ /*! `BitBox` structure | ||
| use crate::{ | ||
| bits::Bits, | ||
| cursor::{ | ||
@@ -18,2 +17,3 @@ BigEndian, | ||
| slice::BitSlice, | ||
| store::BitStore, | ||
| vec::BitVec, | ||
@@ -121,4 +121,5 @@ }; | ||
| retrieve bit values from the storage type. | ||
| - `T: Bits`: An implementor of the [`Bits`] trait: `u8`, `u16`, `u32`, or `u64`. | ||
| This is the actual type in memory that the box will use to store data. | ||
| - `T: BitStore`: An implementor of the [`BitStore`] trait: `u8`, `u16`, `u32`, | ||
| or `u64` (64-bit systems only). This is the actual type in memory that the box | ||
| will use to store data. | ||
@@ -140,3 +141,3 @@ # Safety | ||
| pub struct BitBox<C = BigEndian, T = u8> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| _cursor: PhantomData<C>, | ||
@@ -147,3 +148,3 @@ pointer: BitPtr<T>, | ||
| impl<C, T> BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| /// Constructs an empty boxed bitslice. | ||
@@ -212,8 +213,8 @@ /// | ||
| /// | ||
| /// let src: &[u8] = &[5, 10]; | ||
| /// let bv: BitBox = src.into(); | ||
| /// assert!(bv[5]); | ||
| /// assert!(bv[7]); | ||
| /// assert!(bv[12]); | ||
| /// assert!(bv[14]); | ||
| /// let src = [5, 10]; | ||
| /// let bb: BitBox = BitBox::from_slice(&src[..]); | ||
| /// assert!(bb[5]); | ||
| /// assert!(bb[7]); | ||
| /// assert!(bb[12]); | ||
| /// assert!(bb[14]); | ||
| /// ``` | ||
@@ -240,5 +241,4 @@ pub fn from_slice(slice: &[T]) -> Self { | ||
| /// | ||
| /// let src: &[u8] = &[0, !0]; | ||
| /// let bs: &BitSlice = src.into(); | ||
| /// let bb = BitBox::from_bitslice(bs); | ||
| /// let src = [0u8, !0]; | ||
| /// let bb = BitBox::<BigEndian, _>::from_bitslice(src.as_bitslice()); | ||
| /// assert_eq!(bb.len(), 16); | ||
@@ -388,3 +388,3 @@ /// assert!(bb.some()); | ||
| mem::forget(self); | ||
| out.into() | ||
| out.into_bitslice_mut() | ||
| } | ||
@@ -419,3 +419,3 @@ | ||
| pub fn as_bitslice(&self) -> &BitSlice<C, T> { | ||
| self.pointer.into() | ||
| self.pointer.into_bitslice() | ||
| } | ||
@@ -433,3 +433,3 @@ | ||
| pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<C, T> { | ||
| self.pointer.into() | ||
| self.pointer.into_bitslice_mut() | ||
| } | ||
@@ -480,5 +480,5 @@ | ||
| impl<C, T> Borrow<BitSlice<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn borrow(&self) -> &BitSlice<C, T> { | ||
| &*self | ||
| self.as_bitslice() | ||
| } | ||
@@ -488,5 +488,5 @@ } | ||
| impl<C, T> BorrowMut<BitSlice<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn borrow_mut(&mut self) -> &mut BitSlice<C, T> { | ||
| &mut *self | ||
| self.as_mut_bitslice() | ||
| } | ||
@@ -496,3 +496,3 @@ } | ||
| impl<C, T> Clone for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn clone(&self) -> Self { | ||
@@ -511,6 +511,6 @@ let (e, h, t) = self.bitptr().region_data(); | ||
| impl<C, T> Eq for BitBox<C, T> | ||
| where C: Cursor, T: Bits {} | ||
| where C: Cursor, T: BitStore {} | ||
| impl<C, T> Ord for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn cmp(&self, rhs: &Self) -> Ordering { | ||
@@ -522,3 +522,3 @@ self.as_bitslice().cmp(rhs.as_bitslice()) | ||
| impl<A, B, C, D> PartialEq<BitBox<C, D>> for BitBox<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn eq(&self, rhs: &BitBox<C, D>) -> bool { | ||
@@ -530,3 +530,3 @@ self.as_bitslice().eq(rhs.as_bitslice()) | ||
| impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitBox<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn eq(&self, rhs: &BitSlice<C, D>) -> bool { | ||
@@ -538,3 +538,3 @@ self.as_bitslice().eq(rhs) | ||
| impl<A, B, C, D> PartialEq<BitBox<C, D>> for BitSlice<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn eq(&self, rhs: &BitBox<C, D>) -> bool { | ||
@@ -546,3 +546,3 @@ self.eq(rhs.as_bitslice()) | ||
| impl<A, B, C, D> PartialOrd<BitBox<C, D>> for BitBox<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn partial_cmp(&self, rhs: &BitBox<C, D>) -> Option<Ordering> { | ||
@@ -554,3 +554,3 @@ self.as_bitslice().partial_cmp(rhs.as_bitslice()) | ||
| impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitBox<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> { | ||
@@ -562,3 +562,3 @@ self.as_bitslice().partial_cmp(rhs) | ||
| impl<A, B, C, D> PartialOrd<BitBox<C, D>> for BitSlice<A, B> | ||
| where A: Cursor, B: Bits, C: Cursor, D: Bits { | ||
| where A: Cursor, B: BitStore, C: Cursor, D: BitStore { | ||
| fn partial_cmp(&self, rhs: &BitBox<C, D>) -> Option<Ordering> { | ||
@@ -570,3 +570,3 @@ self.partial_cmp(rhs.as_bitslice()) | ||
| impl<C, T> AsMut<BitSlice<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn as_mut(&mut self) -> &mut BitSlice<C, T> { | ||
@@ -578,3 +578,3 @@ self.as_mut_bitslice() | ||
| impl<C, T> AsMut<[T]> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn as_mut(&mut self) -> &mut [T] { | ||
@@ -586,3 +586,3 @@ self.as_mut_bitslice().as_mut() | ||
| impl<C, T> AsRef<BitSlice<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn as_ref(&self) -> &BitSlice<C, T> { | ||
@@ -594,3 +594,3 @@ self.as_bitslice() | ||
| impl<C, T> AsRef<[T]> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn as_ref(&self) -> &[T] { | ||
@@ -602,3 +602,3 @@ self.as_bitslice().as_ref() | ||
| impl<C, T> From<&BitSlice<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn from(src: &BitSlice<C, T>) -> Self { | ||
@@ -610,3 +610,3 @@ Self::from_bitslice(src) | ||
| impl<C, T> From<&[T]> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn from(src: &[T]) -> Self { | ||
@@ -618,3 +618,3 @@ Self::from_slice(src) | ||
| impl<C, T> From<BitVec<C, T>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn from(src: BitVec<C, T>) -> Self { | ||
@@ -626,3 +626,3 @@ src.into_boxed_bitslice() | ||
| impl<C, T> From<Box<[T]>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn from(src: Box<[T]>) -> Self { | ||
@@ -634,3 +634,3 @@ Self::from_boxed_slice(src) | ||
| impl<C, T> Into<Box<[T]>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn into(self) -> Box<[T]> { | ||
@@ -642,3 +642,3 @@ self.into_boxed_slice() | ||
| impl<C, T> Default for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn default() -> Self { | ||
@@ -653,3 +653,3 @@ Self { | ||
| impl<C, T> Debug for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
@@ -661,3 +661,3 @@ f.write_str("BitBox<")?; | ||
| f.write_str("> ")?; | ||
| Display::fmt(&**self, f) | ||
| Display::fmt(self.as_bitslice(), f) | ||
| } | ||
@@ -667,5 +667,5 @@ } | ||
| impl<C, T> Display for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| Display::fmt(&**self, f) | ||
| Display::fmt(self.as_bitslice(), f) | ||
| } | ||
@@ -675,3 +675,3 @@ } | ||
| impl<C, T> Hash for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
@@ -683,3 +683,3 @@ self.as_bitslice().hash(hasher) | ||
| impl<C, T> IntoIterator for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Item = bool; | ||
@@ -690,4 +690,4 @@ type IntoIter = IntoIter<C, T>; | ||
| IntoIter { | ||
| iterator: self.bitptr(), | ||
| _original: self, | ||
| region: self.bitptr(), | ||
| bitbox: self, | ||
| } | ||
@@ -698,3 +698,3 @@ } | ||
| impl<'a, C, T> IntoIterator for &'a BitBox<C, T> | ||
| where C: Cursor, T: 'a + Bits { | ||
| where C: Cursor, T: 'a + BitStore { | ||
| type Item = bool; | ||
@@ -710,10 +710,10 @@ type IntoIter = <&'a BitSlice<C, T> as IntoIterator>::IntoIter; | ||
| unsafe impl<C, T> Send for BitBox<C, T> | ||
| where C: Cursor, T: Bits {} | ||
| where C: Cursor, T: BitStore {} | ||
| /// `&BitBox` is safe to move across thread boundaries. | ||
| unsafe impl<C, T> Sync for BitBox<C, T> | ||
| where C: Cursor, T: Bits {} | ||
| where C: Cursor, T: BitStore {} | ||
| impl<C, T> Add<Self> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = Self; | ||
@@ -728,5 +728,5 @@ | ||
| impl<C, T> AddAssign for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn add_assign(&mut self, addend: Self) { | ||
| **self += &*addend | ||
| self.as_mut_bitslice().add_assign(addend.as_bitslice()) | ||
| } | ||
@@ -736,3 +736,3 @@ } | ||
| impl<C, T, I> BitAnd<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
@@ -747,5 +747,5 @@ | ||
| impl<C, T, I> BitAndAssign<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| fn bitand_assign(&mut self, rhs: I) { | ||
| **self &= rhs; | ||
| self.as_mut_bitslice().bitand_assign(rhs); | ||
| } | ||
@@ -755,3 +755,3 @@ } | ||
| impl<C, T, I> BitOr<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
@@ -766,5 +766,5 @@ | ||
| impl<C, T, I> BitOrAssign<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| fn bitor_assign(&mut self, rhs: I) { | ||
| **self |= rhs; | ||
| self.as_mut_bitslice().bitor_assign(rhs); | ||
| } | ||
@@ -774,3 +774,3 @@ } | ||
| impl<C, T, I> BitXor<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
@@ -785,5 +785,5 @@ | ||
| impl<C, T, I> BitXorAssign<I> for BitBox<C, T> | ||
| where C: Cursor, T: Bits, I: IntoIterator<Item=bool> { | ||
| where C: Cursor, T: BitStore, I: IntoIterator<Item=bool> { | ||
| fn bitxor_assign(&mut self, rhs: I) { | ||
| **self ^= rhs; | ||
| self.as_mut_bitslice().bitxor_assign(rhs); | ||
| } | ||
@@ -793,7 +793,7 @@ } | ||
| impl<C, T> Deref for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Target = BitSlice<C, T>; | ||
| fn deref(&self) -> &Self::Target { | ||
| self.pointer.into() | ||
| self.as_bitslice() | ||
| } | ||
@@ -803,5 +803,5 @@ } | ||
| impl<C, T> DerefMut for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| self.pointer.into() | ||
| self.as_mut_bitslice() | ||
| } | ||
@@ -811,8 +811,8 @@ } | ||
| impl<C, T> Drop for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn drop(&mut self) { | ||
| let ptr = self.as_mut_bitslice().as_mut_ptr(); | ||
| let len = self.as_bitslice().len(); | ||
| let ptr = self.as_mut_slice().as_mut_ptr(); | ||
| let len = self.as_slice().len(); | ||
| // Run the `Box<[T]>` destructor. | ||
| drop(unsafe { Vec::from_raw_parts(ptr, len, len).into_boxed_slice() }); | ||
| drop(unsafe { Vec::from_raw_parts(ptr, 0, len) }.into_boxed_slice()); | ||
| } | ||
@@ -822,7 +822,7 @@ } | ||
| impl<C, T> Index<usize> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = bool; | ||
| fn index(&self, index: usize) -> &Self::Output { | ||
| &(**self)[index] | ||
| &self.as_bitslice()[index] | ||
| } | ||
@@ -832,7 +832,7 @@ } | ||
| impl<C, T> Index<Range<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: Range<usize>) -> &Self::Output { | ||
| &(**self)[range] | ||
| &self.as_bitslice()[range] | ||
| } | ||
@@ -842,5 +842,5 @@ } | ||
| impl<C, T> IndexMut<Range<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| &mut self.as_mut_bitslice()[range] | ||
| } | ||
@@ -850,7 +850,7 @@ } | ||
| impl<C, T> Index<RangeFrom<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: RangeFrom<usize>) -> &Self::Output { | ||
| &(**self)[range] | ||
| &self.as_bitslice()[range] | ||
| } | ||
@@ -860,5 +860,5 @@ } | ||
| impl<C, T> IndexMut<RangeFrom<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| &mut self.as_mut_bitslice()[range] | ||
| } | ||
@@ -868,7 +868,7 @@ } | ||
| impl<C, T> Index<RangeFull> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: RangeFull) -> &Self::Output { | ||
| &(**self)[range] | ||
| fn index(&self, _: RangeFull) -> &Self::Output { | ||
| self.as_bitslice() | ||
| } | ||
@@ -878,5 +878,5 @@ } | ||
| impl<C, T> IndexMut<RangeFull> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| fn index_mut(&mut self, range: RangeFull) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output { | ||
| self.as_mut_bitslice() | ||
| } | ||
@@ -886,7 +886,7 @@ } | ||
| impl<C, T> Index<RangeInclusive<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: RangeInclusive<usize>) -> &Self::Output { | ||
| &(**self)[range] | ||
| &self.as_bitslice()[range] | ||
| } | ||
@@ -896,5 +896,5 @@ } | ||
| impl<C, T> IndexMut<RangeInclusive<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| &mut self.as_mut_bitslice()[range] | ||
| } | ||
@@ -904,7 +904,7 @@ } | ||
| impl<C, T> Index<RangeTo<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: RangeTo<usize>) -> &Self::Output { | ||
| &(**self)[range] | ||
| &self.as_bitslice()[range] | ||
| } | ||
@@ -914,5 +914,5 @@ } | ||
| impl<C, T> IndexMut<RangeTo<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| &mut self.as_mut_bitslice()[range] | ||
| } | ||
@@ -922,7 +922,7 @@ } | ||
| impl<C, T> Index<RangeToInclusive<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = BitSlice<C, T>; | ||
| fn index(&self, range: RangeToInclusive<usize>) -> &Self::Output { | ||
| &(**self)[range] | ||
| &self.as_bitslice()[range] | ||
| } | ||
@@ -932,5 +932,8 @@ } | ||
| impl<C, T> IndexMut<RangeToInclusive<usize>> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| fn index_mut(&mut self, range: RangeToInclusive<usize>) -> &mut Self::Output { | ||
| &mut (**self)[range] | ||
| where C: Cursor, T: BitStore { | ||
| fn index_mut( | ||
| &mut self, | ||
| range: RangeToInclusive<usize>, | ||
| ) -> &mut Self::Output { | ||
| &mut self.as_mut_bitslice()[range] | ||
| } | ||
@@ -940,7 +943,7 @@ } | ||
| impl<C, T> Neg for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = Self; | ||
| fn neg(mut self) -> Self::Output { | ||
| let _ = -(&mut *self); | ||
| let _ = self.as_mut_bitslice().neg(); | ||
| self | ||
@@ -951,7 +954,7 @@ } | ||
| impl<C, T> Not for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = Self; | ||
| fn not(mut self) -> Self::Output { | ||
| let _ = !(&mut *self); | ||
| let _ = self.as_mut_bitslice().not(); | ||
| self | ||
@@ -962,3 +965,3 @@ } | ||
| impl<C, T> Shl<usize> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = Self; | ||
@@ -973,5 +976,5 @@ | ||
| impl<C, T> ShlAssign<usize> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn shl_assign(&mut self, shamt: usize) { | ||
| **self <<= shamt; | ||
| self.as_mut_bitslice().shl_assign(shamt); | ||
| } | ||
@@ -981,3 +984,3 @@ } | ||
| impl<C, T> Shr<usize> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Output = Self; | ||
@@ -992,5 +995,5 @@ | ||
| impl<C, T> ShrAssign<usize> for BitBox<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn shr_assign(&mut self, shamt: usize) { | ||
| **self >>= shamt; | ||
| self.as_mut_bitslice().shr_assign(shamt); | ||
| } | ||
@@ -1001,13 +1004,13 @@ } | ||
| pub struct IntoIter<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| /// Owning pointer to the full slab | ||
| _original: BitBox<C, T>, | ||
| bitbox: BitBox<C, T>, | ||
| /// Slice descriptor for the region undergoing iteration. | ||
| iterator: BitPtr<T>, | ||
| region: BitPtr<T>, | ||
| } | ||
| impl<C, T> IntoIter<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn iterator(&self) -> <&BitSlice<C, T> as IntoIterator>::IntoIter { | ||
| <&BitSlice<C, T>>::from(self.iterator).into_iter() | ||
| self.region.into_bitslice().into_iter() | ||
| } | ||
@@ -1017,7 +1020,7 @@ } | ||
| impl<C, T> DoubleEndedIterator for IntoIter<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| fn next_back(&mut self) -> Option<Self::Item> { | ||
| let mut slice_iter = self.iterator(); | ||
| let out = slice_iter.next_back(); | ||
| self.iterator = slice_iter.bitptr(); | ||
| self.region = slice_iter.bitptr(); | ||
| out | ||
@@ -1028,9 +1031,9 @@ } | ||
| impl<C, T> ExactSizeIterator for IntoIter<C, T> | ||
| where C: Cursor, T: Bits {} | ||
| where C: Cursor, T: BitStore {} | ||
| impl<C, T> FusedIterator for IntoIter<C, T> | ||
| where C: Cursor, T: Bits {} | ||
| where C: Cursor, T: BitStore {} | ||
| impl<C, T> Iterator for IntoIter<C, T> | ||
| where C: Cursor, T: Bits { | ||
| where C: Cursor, T: BitStore { | ||
| type Item = bool; | ||
@@ -1041,3 +1044,3 @@ | ||
| let out = slice_iter.next(); | ||
| self.iterator = slice_iter.bitptr(); | ||
| self.region = slice_iter.bitptr(); | ||
| out | ||
@@ -1057,3 +1060,3 @@ } | ||
| let out = slice_iter.nth(n); | ||
| self.iterator = slice_iter.bitptr(); | ||
| self.region = slice_iter.bitptr(); | ||
| out | ||
@@ -1060,0 +1063,0 @@ } |
+10
-6
@@ -17,6 +17,6 @@ /*! Bit Cursors | ||
| use super::bits::{ | ||
| use crate::store::{ | ||
| BitIdx, | ||
| BitPos, | ||
| Bits, | ||
| BitStore, | ||
| }; | ||
@@ -58,3 +58,4 @@ | ||
| /// | ||
| /// - `T: Bits`: The storage type for which the position will be calculated. | ||
| /// - `T: BitStore`: The storage type for which the position will be | ||
| /// calculated. | ||
| /// | ||
@@ -96,3 +97,4 @@ /// # Invariants | ||
| /// `T::BITS ..` will induce panics elsewhere in the library. | ||
| fn at<T: Bits>(cursor: BitIdx) -> BitPos; | ||
| fn at<T>(cursor: BitIdx) -> BitPos | ||
| where T: BitStore; | ||
| } | ||
@@ -106,3 +108,4 @@ | ||
| /// `BigEndian` order moves from `MSbit` first to `LSbit` last. | ||
| fn at<T: Bits>(cursor: BitIdx) -> BitPos { | ||
| fn at<T>(cursor: BitIdx) -> BitPos | ||
| where T: BitStore { | ||
| assert!( | ||
@@ -125,3 +128,4 @@ cursor.is_valid::<T>(), | ||
| /// `LittleEndian` order moves from `LSbit` first to `MSbit` last. | ||
| fn at<T: Bits>(cursor: BitIdx) -> BitPos { | ||
| fn at<T>(cursor: BitIdx) -> BitPos | ||
| where T: BitStore { | ||
| assert!( | ||
@@ -128,0 +132,0 @@ cursor.is_valid::<T>(), |
+38
-12
@@ -11,7 +11,7 @@ /*! Data Model for Bit Sequence Domains | ||
| use crate::{ | ||
| bits::{ | ||
| pointer::BitPtr, | ||
| store::{ | ||
| BitIdx, | ||
| Bits, | ||
| BitStore, | ||
| }, | ||
| pointer::BitPtr, | ||
| }; | ||
@@ -52,3 +52,3 @@ | ||
| impl<T> From<&BitPtr<T>> for BitDomainKind | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| fn from(bitptr: &BitPtr<T>) -> Self { | ||
@@ -83,6 +83,6 @@ let (e, h, t) = bitptr.region_data(); | ||
| /// | ||
| /// - `T: Bits` The type of the elements the domain inhabits. | ||
| /// - `T: BitStore` The type of the elements the domain inhabits. | ||
| #[derive(Clone, Debug)] | ||
| pub enum BitDomain<'a, T> | ||
| where T: 'a + Bits { | ||
| where T: 'a + BitStore { | ||
| /// Empty domain. | ||
@@ -101,3 +101,3 @@ Empty, | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// - `.1` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// - `.2` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
@@ -121,2 +121,7 @@ /// # Behavior | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// - `.4` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -136,2 +141,6 @@ /// | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -150,2 +159,6 @@ /// | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.2` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -170,3 +183,3 @@ /// | ||
| impl<'a, T> From<BitPtr<T>> for BitDomain<'a, T> | ||
| where T: 'a + Bits { | ||
| where T: 'a + BitStore { | ||
| fn from(bitptr: BitPtr<T>) -> Self { | ||
@@ -202,6 +215,6 @@ use BitDomainKind as Bdk; | ||
| /// | ||
| /// - `T: Bits` The type of the elements the domain inhabits. | ||
| /// - `T: BitStore` The type of the elements the domain inhabits. | ||
| #[derive(Debug)] | ||
| pub enum BitDomainMut<'a, T> | ||
| where T: 'a + Bits { | ||
| where T: 'a + BitStore { | ||
| /// Empty domain. | ||
@@ -220,3 +233,3 @@ Empty, | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// - `.1` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// - `.2` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
@@ -240,2 +253,7 @@ /// # Behavior | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// - `.4` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -256,2 +274,6 @@ /// | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.0` must satisfy `BitIdx::is_valid::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -271,2 +293,6 @@ /// | ||
| /// | ||
| /// # Invariants | ||
| /// | ||
| /// - `.2` must satisfy `BitIdx::is_valid_tail::<T>` | ||
| /// | ||
| /// # Behavior | ||
@@ -291,3 +317,3 @@ /// | ||
| impl<'a, T> From<BitPtr<T>> for BitDomainMut<'a, T> | ||
| where T: 'a + Bits { | ||
| where T: 'a + BitStore { | ||
| fn from(bitptr: BitPtr<T>) -> Self { | ||
@@ -294,0 +320,0 @@ use BitDomainKind as Bdk; |
+2
-1
@@ -61,2 +61,3 @@ /*! `bitvec` – `[bool]` in overdrive. | ||
| pub mod slice; | ||
| pub mod store; | ||
@@ -79,3 +80,2 @@ #[cfg(any(feature = "alloc", feature = "std"))] | ||
| pub use crate::{ | ||
| bits::*, | ||
| domain::*, | ||
@@ -85,4 +85,5 @@ macros::*, | ||
| slice::*, | ||
| store::*, | ||
| vec::*, | ||
| }; | ||
| } |
+74
-74
@@ -10,11 +10,11 @@ /*! Utility macros for constructing data structures and implementing bulk types. | ||
| `bitvec!` can be invoked in a number of ways. It takes the name of a `Cursor` | ||
| implementation, the name of a `Bits`-implementing fundamental, and zero or more | ||
| fundamentals (integer, floating-point, or boolean) which are used to build the | ||
| bits. Each fundamental literal corresponds to one bit, and is considered to | ||
| implementation, the name of a `BitStore`-implementing fundamental, and zero or | ||
| more fundamentals (integer, floating-point, or boolean) which are used to build | ||
| the bits. Each fundamental literal corresponds to one bit, and is considered to | ||
| represent `1` if it is any other value than exactly zero. | ||
| `bitvec!` can be invoked with no specifiers, a `Cursor` specifier, or a `Cursor` | ||
| and a `Bits` specifier. It cannot be invoked with a `Bits` specifier but no | ||
| `Cursor` specifier, due to overlap in how those tokens are matched by the macro | ||
| system. | ||
| and a `BitStore` specifier. It cannot be invoked with a `BitStore` specifier but | ||
| no `Cursor` specifier, due to overlap in how those tokens are matched by the | ||
| macro system. | ||
@@ -44,17 +44,17 @@ Like `vec!`, `bitvec!` supports bit lists `[0, 1, …]` and repetition markers | ||
| // bitvec![ endian , type ; 0 , 1 , … ] | ||
| ( $endian:path , $bits:ty ; $( $element:expr ),* ) => { | ||
| bitvec![ __bv_impl__ $endian , $bits ; $( $element ),* ] | ||
| ( $cursor:path , $bits:ty ; $( $element:expr ),* ) => { | ||
| bitvec![ __bv_impl__ $cursor , $bits ; $( $element ),* ] | ||
| }; | ||
| // bitvec![ endian , type ; 0 , 1 , … , ] | ||
| ( $endian:path , $bits:ty ; $( $element:expr , )* ) => { | ||
| bitvec![ __bv_impl__ $endian , $bits ; $( $element ),* ] | ||
| ( $cursor:path , $bits:ty ; $( $element:expr , )* ) => { | ||
| bitvec![ __bv_impl__ $cursor , $bits ; $( $element ),* ] | ||
| }; | ||
| // bitvec![ endian ; 0 , 1 , … ] | ||
| ( $endian:path ; $( $element:expr ),* ) => { | ||
| bitvec![ __bv_impl__ $endian , u8 ; $( $element ),* ] | ||
| ( $cursor:path ; $( $element:expr ),* ) => { | ||
| bitvec![ __bv_impl__ $cursor , u8 ; $( $element ),* ] | ||
| }; | ||
| // bitvec![ endian ; 0 , 1 , … , ] | ||
| ( $endian:path ; $( $element:expr , )* ) => { | ||
| bitvec![ __bv_impl__ $endian , u8 ; $( $element ),* ] | ||
| ( $cursor:path ; $( $element:expr , )* ) => { | ||
| bitvec![ __bv_impl__ $cursor , u8 ; $( $element ),* ] | ||
| }; | ||
@@ -72,8 +72,8 @@ | ||
| // bitvec![ endian , type ; bit ; rep ] | ||
| ( $endian:path , $bits:ty ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ __bv_impl__ $endian , $bits ; $element; $rep ] | ||
| ( $cursor:path , $bits:ty ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ __bv_impl__ $cursor , $bits ; $element; $rep ] | ||
| }; | ||
| // bitvec![ endian ; bit ; rep ] | ||
| ( $endian:path ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ __bv_impl__ $endian , u8 ; $element ; $rep ] | ||
| ( $cursor:path ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ __bv_impl__ $cursor , u8 ; $element ; $rep ] | ||
| }; | ||
@@ -93,11 +93,11 @@ // bitvec![ bit ; rep ] | ||
| ( __bv_impl__ $endian:path , $bits:ty ; $( $element:expr ),* ) => {{ | ||
| ( __bv_impl__ $cursor:path , $bits:ty ; $( $element:expr ),* ) => {{ | ||
| let init: &[bool] = &[ $( $element != 0 ),* ]; | ||
| $crate :: vec :: BitVec :: < $endian , $bits > :: from ( init ) | ||
| $crate::vec::BitVec::<$cursor, $bits>::from(init) | ||
| }}; | ||
| ( __bv_impl__ $endian:path , $bits:ty ; $element:expr ; $rep:expr ) => {{ | ||
| core :: iter :: repeat ( $element != 0 ) | ||
| .take ( $rep ) | ||
| .collect :: < $crate :: vec :: BitVec < $endian , $bits > > ( ) | ||
| ( __bv_impl__ $cursor:path , $bits:ty ; $element:expr ; $rep:expr ) => {{ | ||
| core::iter::repeat($element != 0) | ||
| .take($rep) | ||
| .collect::<$crate::vec::BitVec<$cursor, $bits>>() | ||
| }}; | ||
@@ -118,17 +118,17 @@ } | ||
| // bitbox![ endian , type ; 0 , 1 , … ] | ||
| ( $endian:path , $bits:ty ; $( $element:expr ),* ) => { | ||
| bitvec![ $endian , $bits ; $( $element ),* ].into_boxed_bitslice() | ||
| ( $cursor:path , $bits:ty ; $( $element:expr ),* ) => { | ||
| bitvec![ $cursor , $bits ; $( $element ),* ].into_boxed_bitslice() | ||
| }; | ||
| // bitbox![ endian , type ; 0 , 1 , … , ] | ||
| ( $endian:path , $bits:ty ; $( $element:expr , )* ) => { | ||
| bitvec![ $endian , $bits ; $( $element ),* ].into_boxed_bitslice() | ||
| ( $cursor:path , $bits:ty ; $( $element:expr , )* ) => { | ||
| bitvec![ $cursor , $bits ; $( $element ),* ].into_boxed_bitslice() | ||
| }; | ||
| // bitbox![ endian ; 0 , 1 , … ] | ||
| ( $endian:path ; $( $element:expr ),* ) => { | ||
| bitvec![ $endian , u8 ; $( $element ),* ].into_boxed_bitslice() | ||
| ( $cursor:path ; $( $element:expr ),* ) => { | ||
| bitvec![ $cursor , u8 ; $( $element ),* ].into_boxed_bitslice() | ||
| }; | ||
| // bitbox![ endian ; 0 , 1 , … , ] | ||
| ( $endian:path ; $( $element:expr , )* ) => { | ||
| bitvec![ $endian , u8 ; $( $element ),* ].into_boxed_bitslice() | ||
| ( $cursor:path ; $( $element:expr , )* ) => { | ||
| bitvec![ $cursor , u8 ; $( $element ),* ].into_boxed_bitslice() | ||
| }; | ||
@@ -146,8 +146,8 @@ | ||
| // bitbox![ endian , type ; bit ; rep ] | ||
| ( $endian:path , $bits:ty ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ $endian , $bits ; $element; $rep ].into_boxed_bitslice() | ||
| ( $cursor:path , $bits:ty ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ $cursor , $bits ; $element; $rep ].into_boxed_bitslice() | ||
| }; | ||
| // bitbox![ endian ; bit ; rep ] | ||
| ( $endian:path ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ $endian , u8 ; $element ; $rep ].into_boxed_bitslice() | ||
| ( $cursor:path ; $element:expr ; $rep:expr ) => { | ||
| bitvec![ $cursor , u8 ; $element ; $rep ].into_boxed_bitslice() | ||
| }; | ||
@@ -164,9 +164,9 @@ // bitbox![ bit ; rep ] | ||
| #[doc(hidden)] | ||
| impl < C , T > core :: ops :: ShlAssign < $t > | ||
| for $crate :: prelude :: BitSlice < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| fn shl_assign ( & mut self , shamt : $t ) { | ||
| core :: ops :: ShlAssign :: < usize > :: shl_assign ( | ||
| self , | ||
| shamt as usize , | ||
| impl<C, T >core::ops::ShlAssign<$t> | ||
| for $crate::prelude::BitSlice<C,T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| fn shl_assign(&mut self, shamt: $t) { | ||
| core::ops::ShlAssign::<usize>::shl_assign( | ||
| self, | ||
| shamt as usize, | ||
| ) | ||
@@ -177,9 +177,9 @@ } | ||
| #[doc(hidden)] | ||
| impl < C , T > core :: ops :: ShrAssign < $t > | ||
| for $crate :: prelude :: BitSlice < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| fn shr_assign ( & mut self , shamt : $t ) { | ||
| core :: ops :: ShrAssign :: < usize > :: shr_assign ( | ||
| impl<C, T> core::ops::ShrAssign<$t> | ||
| for $crate::prelude::BitSlice<C,T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| fn shr_assign(&mut self,shamt: $t){ | ||
| core::ops::ShrAssign::<usize>::shr_assign( | ||
| self, | ||
| shamt as usize , | ||
| shamt as usize, | ||
| ) | ||
@@ -196,9 +196,9 @@ } | ||
| #[doc(hidden)] | ||
| impl < C , T > core :: ops :: Shl < $t > | ||
| for $crate :: vec :: BitVec < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| type Output = < Self as core :: ops :: Shl < usize > > :: Output ; | ||
| impl<C, T> core::ops::Shl<$t> | ||
| for $crate::vec::BitVec<C, T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| type Output = <Self as core::ops::Shl<usize>>::Output; | ||
| fn shl ( self , shamt : $t ) -> Self :: Output { | ||
| core :: ops :: Shl :: < usize > :: shl ( self , shamt as usize ) | ||
| fn shl(self, shamt: $t) -> Self::Output { | ||
| core::ops::Shl::<usize>::shl(self, shamt as usize) | ||
| } | ||
@@ -208,8 +208,8 @@ } | ||
| #[doc(hidden)] | ||
| impl < C , T > core :: ops :: ShlAssign < $t > | ||
| for $crate :: vec :: BitVec < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| fn shl_assign ( & mut self , shamt : $t ) { | ||
| core :: ops :: ShlAssign :: < usize > :: shl_assign ( | ||
| self , | ||
| impl<C, T> core::ops::ShlAssign<$t> | ||
| for $crate::vec::BitVec<C, T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| fn shl_assign(&mut self, shamt: $t) { | ||
| core::ops::ShlAssign::<usize>::shl_assign( | ||
| self, | ||
| shamt as usize, | ||
@@ -221,9 +221,9 @@ ) | ||
| #[doc(hidden)] | ||
| impl < C , T > core :: ops :: Shr < $t > | ||
| for $crate :: vec :: BitVec < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| type Output = < Self as core :: ops :: Shr < usize > > :: Output ; | ||
| impl<C, T> core::ops::Shr<$t> | ||
| for $crate::vec::BitVec<C, T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| type Output = <Self as core::ops::Shr<usize>>::Output; | ||
| fn shr ( self , shamt : $t ) -> Self :: Output { | ||
| core :: ops :: Shr :: < usize > :: shr ( self , shamt as usize ) | ||
| fn shr(self, shamt: $t) -> Self::Output { | ||
| core::ops::Shr::<usize>::shr(self, shamt as usize) | ||
| } | ||
@@ -233,9 +233,9 @@ } | ||
| #[doc(hidden)] | ||
| impl < C , T> core :: ops :: ShrAssign < $t > | ||
| for $crate :: vec :: BitVec < C , T > | ||
| where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits { | ||
| fn shr_assign ( & mut self , shamt : $t ) { | ||
| core :: ops :: ShrAssign :: < usize > :: shr_assign ( | ||
| self , | ||
| shamt as usize , | ||
| impl<C, T> core::ops::ShrAssign<$t> | ||
| for $crate::vec::BitVec<C, T> | ||
| where C: $crate::cursor::Cursor, T: $crate::store::BitStore { | ||
| fn shr_assign(&mut self, shamt: $t) { | ||
| core::ops::ShrAssign::<usize>::shr_assign( | ||
| self, | ||
| shamt as usize, | ||
| ) | ||
@@ -242,0 +242,0 @@ } |
+38
-34
@@ -10,9 +10,9 @@ /*! Raw Pointer Representation | ||
| use crate::{ | ||
| bits::{ | ||
| BitIdx, | ||
| Bits, | ||
| }, | ||
| cursor::Cursor, | ||
| domain::*, | ||
| slice::BitSlice, | ||
| store::{ | ||
| BitIdx, | ||
| BitStore, | ||
| }, | ||
| }; | ||
@@ -61,3 +61,3 @@ | ||
| #[doc(hidden)] | ||
| pub union Pointer<T> { | ||
| pub(crate) union Pointer<T> { | ||
| /// A read pointer to some data. | ||
@@ -253,3 +253,3 @@ r: *const T, | ||
| - `T: Bits` is the storage type over which the pointer governs. | ||
| - `T: BitStore` is the storage type over which the pointer governs. | ||
@@ -275,3 +275,3 @@ # Safety | ||
| pub struct BitPtr<T = u8> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| _ty: PhantomData<T>, | ||
@@ -304,3 +304,3 @@ /// Two-element bitfield structure, holding pointer and head information. | ||
| impl<T> BitPtr<T> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| /// The number of high bits in `self.ptr` that are actually the address of | ||
@@ -400,3 +400,3 @@ /// the zeroth `T`. | ||
| /// memory model and allocation regime. | ||
| pub fn uninhabited(ptr: impl Into<Pointer<T>>) -> Self { | ||
| pub(crate) fn uninhabited(ptr: impl Into<Pointer<T>>) -> Self { | ||
| let ptr = ptr.into(); | ||
@@ -427,5 +427,5 @@ // Check that the pointer is properly aligned for the storage type. | ||
| /// - `elts`: A number of storage elements in the domain of the new | ||
| /// `BitPtr`. This number must be in `0 .. Self::MAX_ELTS`. If it is zero, | ||
| /// then the empty-slice representation is returned, regardless of other | ||
| /// argument values. | ||
| /// `BitPtr`. This number must be in `0 ..= Self::MAX_ELTS`. If it is | ||
| /// zero, then the empty-slice representation is returned, regardless of | ||
| /// other argument values. | ||
| /// - `head`: The bit index of the first live bit in the domain. This must | ||
@@ -460,3 +460,3 @@ /// be in the domain `0 .. T::BITS`. | ||
| /// - If the `elts` counter is not within the countable elements domain, | ||
| /// `0 .. Self::MAX_ELTS`, | ||
| /// `0 ..= Self::MAX_ELTS`, | ||
| /// - If the `data` pointer is so high in the address space that addressing | ||
@@ -473,3 +473,3 @@ /// the last element would cause the pointer to wrap, | ||
| /// of memory that the new `BitPtr` will govern is all governable. | ||
| pub fn new( | ||
| pub(crate) fn new( | ||
| data: impl Into<Pointer<T>>, | ||
@@ -497,3 +497,3 @@ elts: usize, | ||
| elts <= Self::MAX_ELTS, | ||
| "{} exceeds the BitPtr domain maximum, {}", | ||
| "{} is outside the element count domain 1 ..= {}", | ||
| elts, | ||
@@ -507,3 +507,3 @@ Self::MAX_ELTS, | ||
| "{} is outside the head domain 0 .. {}", | ||
| *head, | ||
| head, | ||
| T::BITS, | ||
@@ -516,3 +516,3 @@ ); | ||
| "{} is outside the tail domain 1 ..= {}", | ||
| *tail, | ||
| tail, | ||
| T::BITS, | ||
@@ -535,3 +535,3 @@ ); | ||
| cursor in 1 .. {}", | ||
| *tail, | ||
| tail, | ||
| T::BITS, | ||
@@ -622,3 +622,3 @@ ); | ||
| /// regime in order for the caller to dereference it. | ||
| pub fn pointer(&self) -> Pointer<T> { | ||
| pub(crate) fn pointer(&self) -> Pointer<T> { | ||
| (self.ptr.as_ptr() as usize & Self::PTR_DATA_MASK).into() | ||
@@ -714,7 +714,8 @@ } | ||
| /// | ||
| /// - `Pointer<T>`: A well aligned pointer to the first element of the slice. | ||
| /// - `Pointer<T>`: A well aligned pointer to the first element of the | ||
| /// slice. | ||
| /// - `usize`: The number of elements in the slice. | ||
| /// - `BitIdx`: The index of the first live bit in the first element. | ||
| /// - `BitIdx`: The index of the first dead bit in the last element. | ||
| pub fn raw_parts(&self) -> (Pointer<T>, usize, BitIdx, BitIdx) { | ||
| pub(crate) fn raw_parts(&self) -> (Pointer<T>, usize, BitIdx, BitIdx) { | ||
| (self.pointer(), self.elements(), self.head(), self.tail()) | ||
@@ -1043,3 +1044,3 @@ } | ||
| &*(slice::from_raw_parts( | ||
| self.ptr.as_ptr() as *const u8 as *const (), | ||
| Pointer::from(self.ptr.as_ptr()).r() as *const (), | ||
| self.len, | ||
@@ -1079,3 +1080,3 @@ ) as *const [()] as *const BitSlice<C, T>) | ||
| impl<T> AsMut<[T]> for BitPtr<T> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| fn as_mut(&mut self) -> &mut [T] { | ||
@@ -1089,3 +1090,3 @@ self.as_mut_slice() | ||
| impl<T> AsRef<[T]> for BitPtr<T> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| fn as_ref(&self) -> &[T] { | ||
@@ -1097,3 +1098,3 @@ self.as_slice() | ||
| impl<'a, C, T> From<&'a BitSlice<C, T>> for BitPtr<T> | ||
| where C: Cursor, T: 'a + Bits { | ||
| where C: Cursor, T: 'a + BitStore { | ||
| fn from(src: &'a BitSlice<C, T>) -> Self { | ||
@@ -1105,3 +1106,3 @@ Self::from_bitslice(src) | ||
| impl<'a, C, T> From<&'a mut BitSlice<C, T>> for BitPtr<T> | ||
| where C: Cursor, T: 'a + Bits { | ||
| where C: Cursor, T: 'a + BitStore { | ||
| fn from(src: &'a mut BitSlice<C, T>) -> Self { | ||
@@ -1114,3 +1115,3 @@ Self::from_bitslice(src) | ||
| impl<T> Default for BitPtr<T> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| /// Produces an empty-slice representation. | ||
@@ -1128,10 +1129,11 @@ /// | ||
| impl<T> Debug for BitPtr<T> | ||
| where T: Bits { | ||
| where T: BitStore { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| struct HexPtr<T: Bits>(*const T); | ||
| impl<T: Bits> Debug for HexPtr<T> { | ||
| struct HexPtr<T: BitStore>(*const T); | ||
| impl<T: BitStore> Debug for HexPtr<T> { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| f.write_fmt(format_args!("0x{:0>1$X}", self.0 as usize, PTR_BITS >> 2)) | ||
| write!(f, "0x{:0>1$X}", self.0 as usize, PTR_BITS >> 2) | ||
| } | ||
| } | ||
| struct HexAddr(usize); | ||
@@ -1143,8 +1145,10 @@ impl Debug for HexAddr { | ||
| } | ||
| struct BinAddr<T: Bits>(BitIdx, PhantomData<T>); | ||
| impl<T: Bits> Debug for BinAddr<T> { | ||
| struct BinAddr<T: BitStore>(BitIdx, PhantomData<T>); | ||
| impl<T: BitStore> Debug for BinAddr<T> { | ||
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
| f.write_fmt(format_args!("0b{:0>1$b}", *self.0, T::INDX as usize)) | ||
| write!(f, "0b{:0>1$b}", *self.0, T::INDX as usize) | ||
| } | ||
| } | ||
| write!(f, "BitPtr<{}>", T::TYPENAME)?; | ||
@@ -1151,0 +1155,0 @@ f.debug_struct("") |
+5
-1
@@ -8,3 +8,6 @@ /*! `bitvec` Prelude | ||
| pub use crate::{ | ||
| bits::Bits, | ||
| bits::{ | ||
| Bits, | ||
| BitsMut, | ||
| }, | ||
| cursor::{ | ||
@@ -16,2 +19,3 @@ Cursor, | ||
| slice::BitSlice, | ||
| store::BitStore, | ||
| }; | ||
@@ -18,0 +22,0 @@ |
+9
-9
@@ -13,5 +13,5 @@ /*! `serde`-powered de/serialization | ||
| use crate::{ | ||
| bits::Bits, | ||
| cursor::Cursor, | ||
| slice::BitSlice, | ||
| store::BitStore, | ||
| }; | ||
@@ -61,3 +61,3 @@ | ||
| pub struct BitBoxVisitor<'de, C, T> | ||
| where C: Cursor, T: Bits + Deserialize<'de> { | ||
| where C: Cursor, T: BitStore + Deserialize<'de> { | ||
| _cursor: PhantomData<C>, | ||
@@ -69,3 +69,3 @@ _storage: PhantomData<&'de T>, | ||
| impl<'de, C, T> BitBoxVisitor<'de, C, T> | ||
| where C: Cursor, T: Bits + Deserialize<'de> { | ||
| where C: Cursor, T: BitStore + Deserialize<'de> { | ||
| fn new() -> Self { | ||
@@ -78,3 +78,3 @@ BitBoxVisitor { _cursor: PhantomData, _storage: PhantomData } | ||
| impl<'de, C, T> Visitor<'de> for BitBoxVisitor<'de, C, T> | ||
| where C: Cursor, T: Bits + Deserialize<'de> { | ||
| where C: Cursor, T: BitStore + Deserialize<'de> { | ||
| type Value = BitBox<C, T>; | ||
@@ -150,3 +150,3 @@ | ||
| impl<'de, C, T> Deserialize<'de> for BitBox<C, T> | ||
| where C: Cursor, T: 'de + Bits + Deserialize<'de> { | ||
| where C: Cursor, T: 'de + BitStore + Deserialize<'de> { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
@@ -165,3 +165,3 @@ where D: Deserializer<'de> { | ||
| impl<'de, C, T> Deserialize<'de> for BitVec<C, T> | ||
| where C: Cursor, T: 'de + Bits + Deserialize<'de> { | ||
| where C: Cursor, T: 'de + BitStore + Deserialize<'de> { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
@@ -174,3 +174,3 @@ where D: Deserializer<'de> { | ||
| impl<C, T> Serialize for BitSlice<C, T> | ||
| where C: Cursor, T: Bits + Serialize { | ||
| where C: Cursor, T: BitStore + Serialize { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
@@ -192,3 +192,3 @@ where S: Serializer { | ||
| impl<C, T> Serialize for BitBox<C, T> | ||
| where C: Cursor, T: Bits + Serialize { | ||
| where C: Cursor, T: BitStore + Serialize { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
@@ -202,3 +202,3 @@ where S: Serializer { | ||
| impl<C, T> Serialize for BitVec<C, T> | ||
| where C: Cursor, T: Bits + Serialize { | ||
| where C: Cursor, T: BitStore + Serialize { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
@@ -205,0 +205,0 @@ where S: Serializer { |
| /*! Reserving space when a BitVec is filled to a boundary induces false panic. | ||
| This is due to a faulty validity check (`BitIdx::span` calls `BitIdx::is_valid`) | ||
| called during `BitVec::reserve` using the *tail* of the vector, which at the | ||
| boundary, is a valid tail but not a valid head. | ||
| This is a regression. | ||
| !*/ | ||
| #![cfg(any(feature = "alloc", feature = "std"))] | ||
| use bitvec::prelude::*; | ||
| #[test] | ||
| fn issue_15() { | ||
| let mut bv = bitvec![0; 8]; | ||
| bv.reserve(16); | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display