+1
-1
@@ -15,3 +15,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "bitvec" | ||
| version = "0.4.0" | ||
| version = "0.5.0" | ||
| authors = ["myrrlyn <myrrlyn@outlook.com>"] | ||
@@ -18,0 +18,0 @@ description = "A crate for manipulating memory, bit by bit" |
+27
-0
@@ -5,2 +5,29 @@ # Changelog | ||
| ## 0.5.0 | ||
| ### Added | ||
| - `BitVec` and `BitSlice` implement `Hash`. | ||
| - `BitVec` fully implements addition, negation, and subtraction. | ||
| - `BitSlice` implements in-place addition and negation. | ||
| - `impl AddAssign for BitSlice` | ||
| - `impl Neg for &mut BitSlice` | ||
| This distinction is required in order to match the expectations of the | ||
| arithmetic traits and the realities of immovable `BitSlice`. | ||
| - `BitSlice` offers `.all()`, `.any()`, `.not_all()`, `.not_any()`, and | ||
| `.some()` methods to perform n-ary Boolean logic. | ||
| - `.all()` tests if all bits are set high | ||
| - `.any()` tests if any bits are set high (includes `.all()`) | ||
| - `.not_all()` tests if any bits are set low (includes `.not_all()`) | ||
| - `.not_any()` tests if all bits are set low | ||
| - `.some()` tests if any bits are high and any are low (excludes `.all()` and | ||
| `.not_all()`) | ||
| - `BitSlice` can count how many bits are set high or low with `.count_one()` and | ||
| `.count_zero()`. | ||
| ## 0.4.0 | ||
@@ -7,0 +34,0 @@ |
+1
-1
@@ -41,3 +41,3 @@ # `BitVec` – Managing memory bit by bit | ||
| [dependencies] | ||
| bitvec = "0.4" | ||
| bitvec = "0.5" | ||
| ``` | ||
@@ -44,0 +44,0 @@ |
+591
-231
@@ -55,4 +55,4 @@ /*! `BitSlice` Wide Reference | ||
| use std::convert::{ | ||
| AsMut, | ||
| AsRef, | ||
| AsMut, | ||
| From, | ||
@@ -66,2 +66,6 @@ }; | ||
| }; | ||
| use std::hash::{ | ||
| Hash, | ||
| Hasher, | ||
| }; | ||
| use std::iter::{ | ||
@@ -76,2 +80,3 @@ DoubleEndedIterator, | ||
| use std::ops::{ | ||
| AddAssign, | ||
| BitAndAssign, | ||
@@ -81,2 +86,3 @@ BitOrAssign, | ||
| Index, | ||
| Neg, | ||
| Not, | ||
@@ -117,3 +123,4 @@ ShlAssign, | ||
| #[cfg_attr(nightly, repr(transparent))] | ||
| pub struct BitSlice<E: Endian = BigEndian, T: Bits = u8> { | ||
| pub struct BitSlice<E = BigEndian, T = u8> | ||
| where E: Endian, T: Bits { | ||
| _endian: PhantomData<E>, | ||
@@ -125,3 +132,3 @@ inner: [T], | ||
| where E: Endian, T: Bits { | ||
| /// Gets the bit value at the given position. | ||
| /// Get the bit value at the given position. | ||
| /// | ||
@@ -145,3 +152,3 @@ /// The index value is a semantic count, not a bit address. It converts to a | ||
| /// Sets the bit value at the given position. | ||
| /// Set the bit value at the given position. | ||
| /// | ||
@@ -166,4 +173,13 @@ /// The index value is a semantic count, not a bit address. It converts to a | ||
| /// Returns the number of bits contained in the `BitSlice`. | ||
| /// Return true if *all* bits in the slice are set (logical `∧`). | ||
| /// | ||
| /// # Truth Table | ||
| /// | ||
| /// ```text | ||
| /// 0 0 => 0 | ||
| /// 0 1 => 0 | ||
| /// 1 0 => 0 | ||
| /// 1 1 => 1 | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
@@ -173,2 +189,197 @@ /// | ||
| /// use bitvec::*; | ||
| /// let all = bitvec![1; 10]; | ||
| /// let any = bitvec![0, 0, 1, 0, 0]; | ||
| /// let some = bitvec![1, 1, 0, 1, 1]; | ||
| /// let none = bitvec![0; 10]; | ||
| /// | ||
| /// assert!(all.all()); | ||
| /// assert!(!any.all()); | ||
| /// assert!(!some.all()); | ||
| /// assert!(!none.all()); | ||
| /// ``` | ||
| pub fn all(&self) -> bool { | ||
| // Gallop the filled elements | ||
| let store = self.as_ref(); | ||
| for elt in &store[.. self.elts()] { | ||
| if *elt != T::from(!0) { | ||
| return false; | ||
| } | ||
| } | ||
| // Walk the partial tail | ||
| let bits = self.bits(); | ||
| if bits > 0 { | ||
| let tail = store[self.elts()]; | ||
| for bit in 0 .. bits { | ||
| if !tail.get(E::curr::<T>(bit)) { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| /// Return true if *any* bit in the slice is set (logical `∨`). | ||
| /// | ||
| /// # Truth Table | ||
| /// | ||
| /// ```text | ||
| /// 0 0 => 0 | ||
| /// 0 1 => 1 | ||
| /// 1 0 => 1 | ||
| /// 1 1 => 1 | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let all = bitvec![1; 10]; | ||
| /// let any = bitvec![0, 0, 1, 0, 0]; | ||
| /// let some = bitvec![1, 1, 0, 1, 1]; | ||
| /// let none = bitvec![0; 10]; | ||
| /// | ||
| /// assert!(all.any()); | ||
| /// assert!(any.any()); | ||
| /// assert!(some.any()); | ||
| /// assert!(!none.any()); | ||
| /// ``` | ||
| pub fn any(&self) -> bool { | ||
| // Gallop the filled elements | ||
| let store = self.as_ref(); | ||
| for elt in &store[.. self.elts()] { | ||
| if *elt != T::from(0) { | ||
| return true; | ||
| } | ||
| } | ||
| // Walk the partial tail | ||
| let bits = self.bits(); | ||
| if bits > 0 { | ||
| let tail = store[self.elts()]; | ||
| for bit in 0 .. bits { | ||
| if tail.get(E::curr::<T>(bit)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /// Return true if *any* bit in the slice is unset (logical `¬∧`). | ||
| /// | ||
| /// # Truth Table | ||
| /// | ||
| /// ```text | ||
| /// 0 0 => 1 | ||
| /// 0 1 => 1 | ||
| /// 1 0 => 1 | ||
| /// 1 1 => 0 | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let all = bitvec![1; 10]; | ||
| /// let any = bitvec![0, 0, 1, 0, 0]; | ||
| /// let some = bitvec![1, 1, 0, 1, 1]; | ||
| /// let none = bitvec![0; 10]; | ||
| /// | ||
| /// assert!(!all.not_all()); | ||
| /// assert!(any.not_all()); | ||
| /// assert!(some.not_all()); | ||
| /// assert!(none.not_all()); | ||
| /// ``` | ||
| pub fn not_all(&self) -> bool { | ||
| !self.all() | ||
| } | ||
| /// Return true if *all* bits in the slice are uset (logical `¬∨`). | ||
| /// | ||
| /// # Truth Table | ||
| /// | ||
| /// ```text | ||
| /// 0 0 => 1 | ||
| /// 0 1 => 0 | ||
| /// 1 0 => 0 | ||
| /// 1 1 => 0 | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let all = bitvec![1; 10]; | ||
| /// let any = bitvec![0, 0, 1, 0, 0]; | ||
| /// let some = bitvec![1, 1, 0, 1, 1]; | ||
| /// let none = bitvec![0; 10]; | ||
| /// | ||
| /// assert!(!all.not_any()); | ||
| /// assert!(!any.not_any()); | ||
| /// assert!(!some.not_any()); | ||
| /// assert!(none.not_any()); | ||
| /// ``` | ||
| pub fn not_any(&self) -> bool { | ||
| !self.any() | ||
| } | ||
| /// Return true if some, but not all, bits are set and some, but not all, | ||
| /// are unset. | ||
| /// | ||
| /// # Truth Table | ||
| /// | ||
| /// ```text | ||
| /// 0 0 => 0 | ||
| /// 0 1 => 1 | ||
| /// 1 0 => 1 | ||
| /// 1 1 => 0 | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let all = bitvec![1; 2]; | ||
| /// let some = bitvec![1, 0]; | ||
| /// let none = bitvec![0; 2]; | ||
| /// | ||
| /// assert!(!all.some()); | ||
| /// assert!(some.some()); | ||
| /// assert!(!none.some()); | ||
| /// ``` | ||
| pub fn some(&self) -> bool { | ||
| self.any() && self.not_all() | ||
| } | ||
| /// Count how many bits are set high. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![1, 0, 1, 0, 1]; | ||
| /// assert_eq!(bv.count_one(), 3); | ||
| /// ``` | ||
| pub fn count_one(&self) -> usize { | ||
| self.into_iter().filter(|b| *b).count() | ||
| } | ||
| /// Count how many bits are set low. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![0, 1, 0, 1, 0]; | ||
| /// assert_eq!(bv.count_zero(), 3); | ||
| /// ``` | ||
| pub fn count_zero(&self) -> usize { | ||
| self.into_iter().filter(|b| !b).count() | ||
| } | ||
| /// Return the number of bits contained in the `BitSlice`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![1; 10]; | ||
@@ -182,3 +393,3 @@ /// let bits: &BitSlice = &bv; | ||
| /// Counts how many *whole* storage elements are in the `BitSlice`. | ||
| /// Count how many *whole* storage elements are in the `BitSlice`. | ||
| /// | ||
@@ -208,3 +419,3 @@ /// If the `BitSlice` length is not an even multiple of the width of `T`, | ||
| /// Counts how many bits are in the trailing partial storage element. | ||
| /// Count how many bits are in the trailing partial storage element. | ||
| /// | ||
@@ -234,3 +445,3 @@ /// If the `BitSlice` length is an even multiple of the width of `T`, then | ||
| /// Returns `true` if the slice contains no bits. | ||
| /// Return `true` if the slice contains no bits. | ||
| /// | ||
@@ -374,2 +585,109 @@ /// # Examples | ||
| /// Clone a borrowed `BitSlice` into an owned `BitVec`. | ||
| impl<E, T> ToOwned for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Owned = BitVec<E, T>; | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let src = bitvec![0; 5]; | ||
| /// let src_ref: &BitSlice = &src; | ||
| /// let dst = src_ref.to_owned(); | ||
| /// assert_eq!(src, dst); | ||
| /// ``` | ||
| fn to_owned(&self) -> Self::Owned { | ||
| let mut out = Self::Owned::with_capacity(self.len()); | ||
| unsafe { | ||
| let src = self.as_ptr(); | ||
| let dst = out.as_mut_ptr(); | ||
| let len = self.raw_len(); | ||
| ptr::copy_nonoverlapping(src, dst, len); | ||
| out.set_len(self.len()); | ||
| } | ||
| out | ||
| } | ||
| } | ||
| impl<E, T> Eq for BitSlice<E, T> | ||
| where E: Endian, T: Bits {} | ||
| impl<E, T> Ord for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn cmp(&self, rhs: &Self) -> Ordering { | ||
| match self.partial_cmp(rhs) { | ||
| Some(ord) => ord, | ||
| None => unreachable!("`BitSlice` has a total ordering"), | ||
| } | ||
| } | ||
| } | ||
| /// Test if two `BitSlice`s are semantically — not bitwise — equal. | ||
| /// | ||
| /// It is valid to compare two slices of different endianness or element types. | ||
| /// | ||
| /// The equality condition requires that they have the same number of total bits | ||
| /// and that each pair of bits in semantic order are identical. | ||
| impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitSlice<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `==`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let l: BitVec<LittleEndian, u16> = bitvec![LittleEndian, u16; 0, 1, 0, 1]; | ||
| /// let r: BitVec<BigEndian, u32> = bitvec![BigEndian, u32; 0, 1, 0, 1]; | ||
| /// | ||
| /// let ls: &BitSlice<_, _> = &l; | ||
| /// let rs: &BitSlice<_, _> = &r; | ||
| /// assert!(ls == rs); | ||
| /// ``` | ||
| fn eq(&self, rhs: &BitSlice<C, D>) -> bool { | ||
| let (l, r) = (self.iter(), rhs.iter()); | ||
| if l.len() != r.len() { | ||
| return false; | ||
| } | ||
| l.zip(r).all(|(l, r)| l == r) | ||
| } | ||
| } | ||
| /// Compare two `BitSlice`s by semantic — not bitwise — ordering. | ||
| /// | ||
| /// The comparison sorts by testing each index for one slice to have a set bit | ||
| /// where the other has an unset bit. If the slices are different, the slice | ||
| /// with the set bit sorts greater than the slice with the unset bit. | ||
| /// | ||
| /// If one of the slices is exhausted before they differ, the longer slice is | ||
| /// greater. | ||
| impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitSlice<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `<` or `>`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 1, 0, 0]; | ||
| /// let b = bitvec![0, 1, 0, 1]; | ||
| /// let c = bitvec![0, 1, 0, 1, 1]; | ||
| /// let aref: &BitSlice = &a; | ||
| /// let bref: &BitSlice = &b; | ||
| /// let cref: &BitSlice = &c; | ||
| /// assert!(aref < bref); | ||
| /// assert!(bref < cref); | ||
| /// ``` | ||
| fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> { | ||
| for (l, r) in self.iter().zip(rhs.iter()) { | ||
| match (l, r) { | ||
| (true, false) => return Some(Ordering::Greater), | ||
| (false, true) => return Some(Ordering::Less), | ||
| _ => continue, | ||
| } | ||
| } | ||
| self.len().partial_cmp(&rhs.len()) | ||
| } | ||
| } | ||
| /// Give write access to all elements in the underlying storage, including the | ||
@@ -417,8 +735,8 @@ /// partially-filled tail element (if present). | ||
| /// Performs the Boolean AND operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, clearing all remaining bits in `self`. | ||
| impl<E, T, I> BitAndAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// AND a bitstream inta a slice. | ||
| /// Build a `BitSlice` from a slice of elements. The resulting `BitSlice` will | ||
| /// always completely fill the original slice, and will not have a partial tail. | ||
| impl<'a, E, T> From<&'a [T]> for &'a BitSlice<E, T> | ||
| where E: Endian, T: 'a + Bits { | ||
| /// Wrap an `&[T: Bits]` in an `&BitSlice<E: Endian, T>`. The endianness | ||
| /// must be specified by the call site. The element type cannot be changed. | ||
| /// | ||
@@ -429,12 +747,20 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs &= rhs; | ||
| /// assert_eq!("000100", &format!("{}", lhs)); | ||
| /// let src = vec![1u8, 2, 3]; | ||
| /// let borrow: &[u8] = &src; | ||
| /// let bits: &BitSlice<BigEndian, _> = borrow.into(); | ||
| /// assert_eq!(bits.len(), 24); | ||
| /// assert_eq!(bits.elts(), 3); | ||
| /// assert_eq!(bits.bits(), 0); | ||
| /// assert!(bits.get(7)); // src[0] == 0b0000_0001 | ||
| /// assert!(bits.get(14)); // src[1] == 0b0000_0010 | ||
| /// assert!(bits.get(22)); // src[2] == 0b0000_0011 | ||
| /// assert!(bits.get(23)); | ||
| /// ``` | ||
| fn bitand_assign(&mut self, rhs: I) { | ||
| use std::iter::repeat; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) { | ||
| let val = self.get(idx) & other; | ||
| self.set(idx, val); | ||
| fn from(src: &'a [T]) -> Self { | ||
| let (ptr, len): (*const T, usize) = (src.as_ptr(), src.len()); | ||
| assert!(len <= T::MAX_ELT, "Source slice length out of range!"); | ||
| unsafe { | ||
| mem::transmute( | ||
| slice::from_raw_parts(ptr, len << T::BITS) | ||
| ) | ||
| } | ||
@@ -444,8 +770,10 @@ } | ||
| /// Performs the Boolear OR operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, leaving all remaining bits in `self` as they were. | ||
| impl<E, T, I> BitOrAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// OR a bitstream into a slice. | ||
| /// Build a mutable `BitSlice` from a slice of mutable elements. The resulting | ||
| /// `BitSlice` will always completely fill the original slice, and will not have | ||
| /// a partial tail. | ||
| impl<'a, E, T> From<&'a mut [T]> for &'a mut BitSlice<E, T> | ||
| where E: Endian, T: 'a + Bits { | ||
| /// Wrap an `&mut [T: Bits]` in an `&mut BitSlice<E: Endian, T>`. The | ||
| /// endianness must be specified by the call site. The element type cannot | ||
| /// be changed. | ||
| /// | ||
@@ -456,11 +784,17 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs |= rhs; | ||
| /// assert_eq!("011101", &format!("{}", lhs)); | ||
| /// let mut src = vec![1u8, 2, 3]; | ||
| /// let borrow: &mut [u8] = &mut src; | ||
| /// let bits: &mut BitSlice<LittleEndian, _> = borrow.into(); | ||
| /// // The first bit read is the LSb of the first element, which is set. | ||
| /// assert!(bits.get(0)); | ||
| /// bits.set(0, false); | ||
| /// assert!(!bits.get(0)); | ||
| /// ``` | ||
| fn bitor_assign(&mut self, rhs: I) { | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) | other; | ||
| self.set(idx, val); | ||
| fn from(src: &'a mut [T]) -> Self { | ||
| let (ptr, len): (*mut T, usize) = (src.as_mut_ptr(), src.len()); | ||
| assert!(len <= T::MAX_ELT, "Source slice length out of range!"); | ||
| unsafe { | ||
| mem::transmute( | ||
| slice::from_raw_parts_mut(ptr, len << T::BITS) | ||
| ) | ||
| } | ||
@@ -470,27 +804,2 @@ } | ||
| /// Perform the Boolean XOR operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, leaving all remaining bits in `self` as they were. | ||
| impl<E, T, I> BitXorAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// XOR a bitstream into a slice. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs ^= rhs; | ||
| /// assert_eq!("011001", &format!("{}", lhs)); | ||
| /// ``` | ||
| fn bitxor_assign(&mut self, rhs: I) { | ||
| use std::iter::repeat; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) { | ||
| let val = self.get(idx) ^ other; | ||
| self.set(idx, val); | ||
| } | ||
| } | ||
| } | ||
| /// Print the `BitSlice` for debugging. | ||
@@ -528,3 +837,3 @@ /// | ||
| fmt.write_str(" [")?; | ||
| if alt { writeln!(fmt)?; } | ||
| if alt { writeln!(fmt)?; fmt.write_str(" ")?; } | ||
| self.fmt_body(fmt, true)?; | ||
@@ -562,8 +871,23 @@ if alt { writeln!(fmt)?; } | ||
| /// Build a `BitSlice` from a slice of elements. The resulting `BitSlice` will | ||
| /// always completely fill the original slice, and will not have a partial tail. | ||
| impl<'a, E, T> From<&'a [T]> for &'a BitSlice<E, T> | ||
| impl<E, T> Hash for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn hash<H>(&self, hasher: &mut H) | ||
| where H: Hasher { | ||
| for bit in self { | ||
| hasher.write_u8(bit as u8); | ||
| } | ||
| } | ||
| } | ||
| /// Produce a read-only iterator over all the bits in the `BitSlice`. | ||
| /// | ||
| /// This iterator follows the ordering in the `BitSlice` type, and implements | ||
| /// `ExactSizeIterator` as `BitSlice` has a known, fixed length, and | ||
| /// `DoubleEndedIterator` as it has known ends. | ||
| impl<'a, E, T> IntoIterator for &'a BitSlice<E, T> | ||
| where E: Endian, T: 'a + Bits { | ||
| /// Wrap an `&[T: Bits]` in an `&BitSlice<E: Endian, T>`. The endianness | ||
| /// must be specified by the call site. The element type cannot be changed. | ||
| type Item = bool; | ||
| type IntoIter = Iter<'a, E, T>; | ||
| /// Iterate over the slice. | ||
| /// | ||
@@ -574,20 +898,67 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let src = vec![1u8, 2, 3]; | ||
| /// let borrow: &[u8] = &src; | ||
| /// let bits: &BitSlice<BigEndian, _> = borrow.into(); | ||
| /// assert_eq!(bits.len(), 24); | ||
| /// assert_eq!(bits.elts(), 3); | ||
| /// assert_eq!(bits.bits(), 0); | ||
| /// assert!(bits.get(7)); // src[0] == 0b0000_0001 | ||
| /// assert!(bits.get(14)); // src[1] == 0b0000_0010 | ||
| /// assert!(bits.get(22)); // src[2] == 0b0000_0011 | ||
| /// assert!(bits.get(23)); | ||
| /// let bv = bitvec![1, 0, 1, 0, 1, 1, 0, 0]; | ||
| /// let bref: &BitSlice = &bv; | ||
| /// let mut count = 0; | ||
| /// for bit in bref { | ||
| /// if bit { count += 1; } | ||
| /// } | ||
| /// assert_eq!(count, 4); | ||
| /// ``` | ||
| fn from(src: &'a [T]) -> Self { | ||
| let (ptr, len): (*const T, usize) = (src.as_ptr(), src.len()); | ||
| assert!(len <= T::MAX_ELT, "Source slice length out of range!"); | ||
| unsafe { | ||
| mem::transmute( | ||
| slice::from_raw_parts(ptr, len << T::BITS) | ||
| ) | ||
| fn into_iter(self) -> Self::IntoIter { | ||
| self.into() | ||
| } | ||
| } | ||
| /// Perform unsigned addition in place on a `BitSlice`. | ||
| /// | ||
| /// If the addend `BitSliec` is shorter than `self`, the addend is zero-extended | ||
| /// to the right. If the addend is longer, the excess front length is unused. | ||
| /// | ||
| /// Addition proceeds from the right ends of each slice towards the left. | ||
| /// Because this trait is forbidden from returning anything, the final carry-out | ||
| /// bit is discarded. | ||
| /// | ||
| /// Note that, unlike `BitVec`, there is no subtraction implementation until I | ||
| /// find a subtraction algorithm that does not require modifying the subtrahend. | ||
| /// | ||
| /// Subtraction can be implemented by negating the intended subtrahend yourself, | ||
| /// then using addition, or by using `BitVec`s instead of `BitSlice`s. | ||
| impl<'a, E, T> AddAssign<&'a BitSlice<E, T>> for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Perform unsigned wrapping addition in place. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// This example shows addition of a slice wrapping from MAX to zero. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let nums: [BitVec; 3] = [ | ||
| /// bitvec![1, 1, 1, 0], | ||
| /// bitvec![1, 1, 1, 1], | ||
| /// bitvec![0, 0, 0, 0], | ||
| /// ]; | ||
| /// let one = bitvec![0, 1]; | ||
| /// let mut num = nums[0].clone(); | ||
| /// let numr: &mut BitSlice = &mut num; | ||
| /// *numr += &one; | ||
| /// assert_eq!(numr, &nums[1] as &BitSlice); | ||
| /// *numr += &one; | ||
| /// assert_eq!(numr, &nums[2] as &BitSlice); | ||
| /// ``` | ||
| fn add_assign(&mut self, addend: &'a BitSlice<E, T>) { | ||
| use std::iter::repeat; | ||
| // zero-extend the addend if it's shorter than self | ||
| let mut addend_iter = addend.into_iter().rev().chain(repeat(false)); | ||
| let mut c = false; | ||
| for place in (0 .. self.len()).rev() { | ||
| // See BitVec::AddAssign | ||
| static JUMP: [u8; 8] = [0, 2, 2, 1, 2, 1, 1, 3]; | ||
| let a = self.get(place); | ||
| let b = addend_iter.next().unwrap(); // addend is an infinite source | ||
| let idx = ((c as u8) << 2) | ((a as u8) << 1) | (b as u8); | ||
| let yz = JUMP[idx as usize]; | ||
| let (y, z) = (yz & 2 != 0, yz & 1 != 0); | ||
| self.set(place, y); | ||
| c = z; | ||
| } | ||
@@ -597,10 +968,8 @@ } | ||
| /// Build a mutable `BitSlice` from a slice of mutable elements. The resulting | ||
| /// `BitSlice` will always completely fill the original slice, and will not have | ||
| /// a partial tail. | ||
| impl<'a, E, T> From<&'a mut [T]> for &'a mut BitSlice<E, T> | ||
| where E: Endian, T: 'a + Bits { | ||
| /// Wrap an `&mut [T: Bits]` in an `&mut BitSlice<E: Endian, T>`. The | ||
| /// endianness must be specified by the call site. The element type cannot | ||
| /// be changed. | ||
| /// Perform the Boolean AND operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, clearing all remaining bits in `self`. | ||
| impl<E, T, I> BitAndAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// AND a bitstream inta a slice. | ||
| /// | ||
@@ -611,17 +980,12 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let mut src = vec![1u8, 2, 3]; | ||
| /// let borrow: &mut [u8] = &mut src; | ||
| /// let bits: &mut BitSlice<LittleEndian, _> = borrow.into(); | ||
| /// // The first bit read is the LSb of the first element, which is set. | ||
| /// assert!(bits.get(0)); | ||
| /// bits.set(0, false); | ||
| /// assert!(!bits.get(0)); | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs &= rhs; | ||
| /// assert_eq!("000100", &format!("{}", lhs)); | ||
| /// ``` | ||
| fn from(src: &'a mut [T]) -> Self { | ||
| let (ptr, len): (*mut T, usize) = (src.as_mut_ptr(), src.len()); | ||
| assert!(len <= T::MAX_ELT, "Source slice length out of range!"); | ||
| unsafe { | ||
| mem::transmute( | ||
| slice::from_raw_parts_mut(ptr, len << T::BITS) | ||
| ) | ||
| fn bitand_assign(&mut self, rhs: I) { | ||
| use std::iter::repeat; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) { | ||
| let val = self.get(idx) & other; | ||
| self.set(idx, val); | ||
| } | ||
@@ -631,2 +995,51 @@ } | ||
| /// Perform the Boolean OR operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, leaving all remaining bits in `self` as they were. | ||
| impl<E, T, I> BitOrAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// OR a bitstream into a slice. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs |= rhs; | ||
| /// assert_eq!("011101", &format!("{}", lhs)); | ||
| /// ``` | ||
| fn bitor_assign(&mut self, rhs: I) { | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) | other; | ||
| self.set(idx, val); | ||
| } | ||
| } | ||
| } | ||
| /// Perform the Boolean XOR operation against another bitstream and writes the | ||
| /// result into `self`. If the other bitstream ends before `self` does, it is | ||
| /// extended with zero, leaving all remaining bits in `self` as they were. | ||
| impl<E, T, I> BitXorAssign<I> for BitSlice<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// XOR a bitstream into a slice. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![0, 0, 1, 1]; | ||
| /// *lhs ^= rhs; | ||
| /// assert_eq!("011001", &format!("{}", lhs)); | ||
| /// ``` | ||
| fn bitxor_assign(&mut self, rhs: I) { | ||
| use std::iter::repeat; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter().chain(repeat(false))) { | ||
| let val = self.get(idx) ^ other; | ||
| self.set(idx, val); | ||
| } | ||
| } | ||
| } | ||
| /// Index a single bit by semantic count. The index must be less than the length | ||
@@ -687,28 +1100,82 @@ /// of the `BitSlice`. | ||
| /// Produce a read-only iterator over all the bits in the `BitSlice`. | ||
| /// Perform fixed-width 2's-complement negation of a `BitSlice`. | ||
| /// | ||
| /// This iterator follows the ordering in the `BitSlice` type, and implements | ||
| /// `ExactSizeIterator` as `BitSlice` has a known, fixed length, and | ||
| /// `DoubleEndedIterator` as it has known ends. | ||
| impl<'a, E, T> IntoIterator for &'a BitSlice<E, T> | ||
| /// Unlike the `!` operator (`Not` trait), the unary `-` operator treats the | ||
| /// `BitSlice` as if it represents a signed 2's-complement integer of fixed | ||
| /// width. The negation of a number in 2's complement is defined as its | ||
| /// inversion (using `!`) plus one, and on fixed-width numbers has the following | ||
| /// discontinuities: | ||
| /// | ||
| /// - A slice whose bits are all zero is considered to represent the number zero | ||
| /// which negates as itself. | ||
| /// - A slice whose bits are all one is considered to represent the most | ||
| /// negative number, which has no correpsonding positive number, and thus | ||
| /// negates as zero. | ||
| /// | ||
| /// This behavior was chosen so that all possible values would have *some* | ||
| /// output, and so that repeated application converges at idempotence. The most | ||
| /// negative input can never be reached by negation, but `--MOST_NEG` converges | ||
| /// at the least unreasonable fallback value, 0. | ||
| /// | ||
| /// Because `BitSlice` cannot move, the negation is performed in place. | ||
| impl<'a, E, T> Neg for &'a mut BitSlice<E, T> | ||
| where E: Endian, T: 'a + Bits { | ||
| type Item = bool; | ||
| type IntoIter = Iter<'a, E, T>; | ||
| type Output = Self; | ||
| /// Iterate over the slice. | ||
| /// Perform 2's-complement fixed-width negation. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// The contortions shown here are a result of this operator applying to a | ||
| /// mutable reference, and this example balancing access to the original | ||
| /// `BitVec` for comparison with aquiring a mutable borrow *as a slice* to | ||
| /// ensure that the `BitSlice` implementation is used, not the `BitVec`. | ||
| /// | ||
| /// Negate an arbitrary positive number (first bit unset). | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![1, 0, 1, 0, 1, 1, 0, 0]; | ||
| /// let bref: &BitSlice = &bv; | ||
| /// let mut count = 0; | ||
| /// for bit in bref { | ||
| /// if bit { count += 1; } | ||
| /// } | ||
| /// assert_eq!(count, 4); | ||
| /// let mut num = bitvec![0, 1, 1, 0]; | ||
| /// - (&mut num as &mut BitSlice); | ||
| /// assert_eq!(num, bitvec![1, 0, 1, 0]); | ||
| /// ``` | ||
| fn into_iter(self) -> Self::IntoIter { | ||
| self.into() | ||
| /// | ||
| /// Negate an arbitrary negative number. This example will use the above | ||
| /// result to demonstrate round-trip correctness. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut num = bitvec![1, 0, 1, 0]; | ||
| /// - (&mut num as &mut BitSlice); | ||
| /// assert_eq!(num, bitvec![0, 1, 1, 0]); | ||
| /// ``` | ||
| /// | ||
| /// Negate the most negative number, which will become zero, and show | ||
| /// convergence at zero. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let zero = bitvec![0; 10]; | ||
| /// let mut num = bitvec![1; 10]; | ||
| /// - (&mut num as &mut BitSlice); | ||
| /// assert_eq!(num, zero); | ||
| /// - (&mut num as &mut BitSlice); | ||
| /// assert_eq!(num, zero); | ||
| /// ``` | ||
| fn neg(self) -> Self::Output { | ||
| if self.is_empty() || self.not_any() { | ||
| return self; | ||
| } | ||
| Not::not(&mut *self); | ||
| // Fill an element with all 1 bits | ||
| let elt: [T; 1] = [!T::default()]; | ||
| if self.any() { | ||
| // Turn a slice reference [T; 1] into a bit-slice reference [u1; 1] | ||
| let addend: &BitSlice<E, T> = { | ||
| unsafe { mem::transmute::<&[T], &BitSlice<E, T>>(&elt) } | ||
| }; | ||
| // And add it (if the slice was not all-ones). | ||
| AddAssign::add_assign(&mut *self, addend); | ||
| } | ||
| self | ||
| } | ||
@@ -750,82 +1217,2 @@ } | ||
| /// Test if two `BitSlice`s are semantically — not bitwise — equal. | ||
| /// | ||
| /// It is valid to compare two slices of different endianness or element types. | ||
| /// | ||
| /// The equality condition requires that they have the same number of total bits | ||
| /// and that each pair of bits in semantic order are identical. | ||
| impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitSlice<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `==`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let l: BitVec<LittleEndian, u16> = bitvec![LittleEndian, u16; 0, 1, 0, 1]; | ||
| /// let r: BitVec<BigEndian, u32> = bitvec![BigEndian, u32; 0, 1, 0, 1]; | ||
| /// | ||
| /// let ls: &BitSlice<_, _> = &l; | ||
| /// let rs: &BitSlice<_, _> = &r; | ||
| /// assert!(ls == rs); | ||
| /// ``` | ||
| fn eq(&self, rhs: &BitSlice<C, D>) -> bool { | ||
| let (l, r) = (self.iter(), rhs.iter()); | ||
| if l.len() != r.len() { | ||
| return false; | ||
| } | ||
| l.zip(r).all(|(l, r)| l == r) | ||
| } | ||
| } | ||
| impl<E, T> Eq for BitSlice<E, T> | ||
| where E: Endian, T: Bits {} | ||
| /// Compare two `BitSlice`s by semantic — not bitwise — ordering. | ||
| /// | ||
| /// The comparison sorts by testing each index for one slice to have a set bit | ||
| /// where the other has an unset bit. If the slices are different, the slice | ||
| /// with the set bit sorts greater than the slice with the unset bit. | ||
| /// | ||
| /// If one of the slices is exhausted before they differ, the longer slice is | ||
| /// greater. | ||
| impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitSlice<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `<` or `>`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 1, 0, 0]; | ||
| /// let b = bitvec![0, 1, 0, 1]; | ||
| /// let c = bitvec![0, 1, 0, 1, 1]; | ||
| /// let aref: &BitSlice = &a; | ||
| /// let bref: &BitSlice = &b; | ||
| /// let cref: &BitSlice = &c; | ||
| /// assert!(aref < bref); | ||
| /// assert!(bref < cref); | ||
| /// ``` | ||
| fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> { | ||
| for (l, r) in self.iter().zip(rhs.iter()) { | ||
| match (l, r) { | ||
| (true, false) => return Some(Ordering::Greater), | ||
| (false, true) => return Some(Ordering::Less), | ||
| _ => continue, | ||
| } | ||
| } | ||
| self.len().partial_cmp(&rhs.len()) | ||
| } | ||
| } | ||
| impl<E, T> Ord for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn cmp(&self, rhs: &Self) -> Ordering { | ||
| match self.partial_cmp(rhs) { | ||
| Some(ord) => ord, | ||
| None => unreachable!("`BitSlice` has a total ordering"), | ||
| } | ||
| } | ||
| } | ||
| __bitslice_shift!(u8, u16, u32, u64, i8, i16, i32, i64); | ||
@@ -1016,29 +1403,2 @@ | ||
| /// Clone a borrowed `BitSlice` into an owned `BitVec`. | ||
| impl<E, T> ToOwned for BitSlice<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Owned = BitVec<E, T>; | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let src = bitvec![0; 5]; | ||
| /// let src_ref: &BitSlice = &src; | ||
| /// let dst = src_ref.to_owned(); | ||
| /// assert_eq!(src, dst); | ||
| /// ``` | ||
| fn to_owned(&self) -> Self::Owned { | ||
| let mut out = Self::Owned::with_capacity(self.len()); | ||
| unsafe { | ||
| let src = self.as_ptr(); | ||
| let dst = out.as_mut_ptr(); | ||
| let len = self.raw_len(); | ||
| ptr::copy_nonoverlapping(src, dst, len); | ||
| out.set_len(self.len()); | ||
| } | ||
| out | ||
| } | ||
| } | ||
| /// Permit iteration over a `BitSlice` | ||
@@ -1045,0 +1405,0 @@ #[doc(hidden)] |
+724
-393
@@ -27,2 +27,3 @@ use super::{ | ||
| }; | ||
| use std::default::Default; | ||
| use std::fmt::{ | ||
@@ -34,2 +35,6 @@ self, | ||
| }; | ||
| use std::hash::{ | ||
| Hash, | ||
| Hasher, | ||
| }; | ||
| use std::iter::{ | ||
@@ -46,2 +51,4 @@ DoubleEndedIterator, | ||
| use std::ops::{ | ||
| Add, | ||
| AddAssign, | ||
| BitAnd, | ||
@@ -55,3 +62,5 @@ BitAndAssign, | ||
| DerefMut, | ||
| Drop, | ||
| Index, | ||
| Neg, | ||
| Not, | ||
@@ -62,2 +71,4 @@ Shl, | ||
| ShrAssign, | ||
| Sub, | ||
| SubAssign, | ||
| }; | ||
@@ -268,3 +279,3 @@ use std::ptr; | ||
| /// Shrinks the `BitVec` to the given size, dropping all excess storage. | ||
| /// Shrink the `BitVec` to the given size, dropping all excess storage. | ||
| /// | ||
@@ -443,197 +454,2 @@ /// This does not affect the memory store! It will not zero the raw memory | ||
| /// Give write access to all live elements in the underlying storage, including | ||
| /// the partially-filled tail. | ||
| impl<E, T> AsMut<[T]> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Access the underlying store. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut bv: BitVec = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1]; | ||
| /// for elt in bv.as_mut() { | ||
| /// *elt += 2; | ||
| /// } | ||
| /// assert_eq!(&[2, 0b1000_0010], bv.as_ref()); | ||
| /// ``` | ||
| fn as_mut(&mut self) -> &mut [T] { | ||
| BitSlice::as_mut(self) | ||
| } | ||
| } | ||
| /// Give read access to all live elements in the underlying storage, including | ||
| /// the partially-filled tail. | ||
| impl<E, T> AsRef<[T]> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Access the underlying store. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1]; | ||
| /// assert_eq!(&[0, 0b1000_0000], bv.as_ref()); | ||
| /// ``` | ||
| fn as_ref(&self) -> &[T] { | ||
| BitSlice::as_ref(self) | ||
| } | ||
| } | ||
| /// Perform the Boolean AND operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitAnd<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// AND a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let and = lhs & rhs; | ||
| /// assert_eq!("0001", &format!("{}", and)); | ||
| /// ``` | ||
| fn bitand(mut self, rhs: I) -> Self::Output { | ||
| self &= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean AND operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitAndAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// AND another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src &= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0001", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitand_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) & other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Perform the Boolean OR operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitOr<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// OR a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let or = lhs | rhs; | ||
| /// assert_eq!("0111", &format!("{}", or)); | ||
| /// ``` | ||
| fn bitor(mut self, rhs: I) -> Self::Output { | ||
| self |= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean OR operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitOrAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// OR another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src |= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0111", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitor_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) | other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Perform the Boolean XOR operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitXor<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// XOR a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let xor = lhs ^ rhs; | ||
| /// assert_eq!("0110", &format!("{}", xor)); | ||
| /// ``` | ||
| fn bitxor(mut self, rhs: I) -> Self::Output { | ||
| self ^= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean XOR operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitXorAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// XOR another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src ^= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0110", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitxor_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) ^ other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Signify that `BitSlice` is the borrowed form of `BitVec`. | ||
@@ -701,47 +517,21 @@ impl<E, T> Borrow<BitSlice<E, T>> for BitVec<E, T> | ||
| /// Print the `BitVec` for debugging. | ||
| /// | ||
| /// The output is of the form `BitVec<E, T> [ELT, *]`, where `<E, T>` is the | ||
| /// endianness and element type, with square brackets on each end of the bits | ||
| /// and all the live elements in the vector printed in binary. The printout is | ||
| /// always in semantic order, and may not reflect the underlying store. To see | ||
| /// the underlying store, use `format!("{:?}", self.as_ref());` instead. | ||
| /// | ||
| /// The alternate character `{:#?}` prints each element on its own line, rather | ||
| /// than separated by a space. | ||
| impl<E, T> Debug for BitVec<E, T> | ||
| impl<E, T> Eq for BitVec<E, T> | ||
| where E: Endian, T: Bits {} | ||
| impl<E, T> Ord for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Render the `BitVec` type header and contents for debug. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![LittleEndian, u16; | ||
| /// 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1 | ||
| /// ]; | ||
| /// assert_eq!( | ||
| /// "BitVec<LittleEndian, u16> [0101000011110101]", | ||
| /// &format!("{:?}", bv) | ||
| /// ); | ||
| /// ``` | ||
| fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
| let alt = fmt.alternate(); | ||
| self.fmt_header(fmt)?; | ||
| fmt.write_str(" [")?; | ||
| if alt { writeln!(fmt)?; } | ||
| self.fmt_body(fmt, true)?; | ||
| if alt { writeln!(fmt)?; } | ||
| fmt.write_str("]") | ||
| fn cmp(&self, rhs: &Self) -> Ordering { | ||
| BitSlice::cmp(&self, &rhs) | ||
| } | ||
| } | ||
| /// Reborrow the `BitVec` as a `BitSlice`. | ||
| /// Test if two `BitVec`s are semantically — not bitwise — equal. | ||
| /// | ||
| /// This mimics the separation between `Vec<T>` and `[T]`. | ||
| impl<E, T> Deref for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Target = BitSlice<E, T>; | ||
| /// Dereference `&BitVec` down to `&BitSlice`. | ||
| /// It is valid to compare two vectors of different endianness or element types. | ||
| /// | ||
| /// The equality condition requires that they have the same number of stored | ||
| /// bits and that each pair of bits in semantic order are identical. | ||
| impl<A, B, C, D> PartialEq<BitVec<C, D>> for BitVec<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `==`. | ||
| /// | ||
@@ -752,19 +542,22 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let bv: BitVec = bitvec![1; 4]; | ||
| /// let bref: &BitSlice = &bv; | ||
| /// assert!(bref.get(2)); | ||
| /// let l: BitVec<LittleEndian, u16> = bitvec![LittleEndian, u16; 0, 1, 0, 1]; | ||
| /// let r: BitVec<BigEndian, u32> = bitvec![BigEndian, u32; 0, 1, 0, 1]; | ||
| /// assert!(l == r); | ||
| /// ``` | ||
| fn deref(&self) -> &Self::Target { | ||
| // `BitVec`'s representation of its inner `Vec` matches exactly the | ||
| // invariants of how `BitSlice` references must look. This is fine. | ||
| unsafe { mem::transmute(&self.inner as &[T]) } | ||
| fn eq(&self, rhs: &BitVec<C, D>) -> bool { | ||
| BitSlice::eq(&self, &rhs) | ||
| } | ||
| } | ||
| /// Reborrow the `BitVec` as a `BitSlice`. | ||
| /// Compare two `BitVec`s by semantic — not bitwise — ordering. | ||
| /// | ||
| /// This mimics the separation between `Vec<T>` and `[T]`. | ||
| impl<E, T> DerefMut for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Dereference `&mut BitVec` down to `&mut BitSlice`. | ||
| /// The comparison sorts by testing each index for one vector to have a set bit | ||
| /// where the other vector has an unset bit. If the vectors are different, the | ||
| /// vector with the set bit sorts greater than the vector with the unset bit. | ||
| /// | ||
| /// If one of the vectors is exhausted before they differ, the longer vector is | ||
| /// greater. | ||
| impl<A, B, C, D> PartialOrd<BitVec<C, D>> for BitVec<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `<` or `>`. | ||
| /// | ||
@@ -775,26 +568,19 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let mut bv: BitVec = bitvec![0; 6]; | ||
| /// let bref: &mut BitSlice = &mut bv; | ||
| /// assert!(!bref.get(5)); | ||
| /// bref.set(5, true); | ||
| /// assert!(bref.get(5)); | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 1, 0, 0]; | ||
| /// let b = bitvec![0, 1, 0, 1]; | ||
| /// let c = bitvec![0, 1, 0, 1, 1]; | ||
| /// assert!(a < b); | ||
| /// assert!(b < c); | ||
| /// ``` | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| unsafe { mem::transmute(&mut self.inner as &mut [T]) } | ||
| fn partial_cmp(&self, rhs: &BitVec<C, D>) -> Option<Ordering> { | ||
| BitSlice::partial_cmp(&self, &rhs) | ||
| } | ||
| } | ||
| /// Print the `BitVec` for displaying. | ||
| /// | ||
| /// This prints each element in turn, formatted in binary in semantic order (so | ||
| /// the first bit seen is printed first and the last bit seen printed last). | ||
| /// Each element of storage is separated by a space for ease of reading. | ||
| /// | ||
| /// The alternate character `{:#}` prints each element on its own line. | ||
| /// | ||
| /// To see the in-memory representation, use `AsRef` to get access to the raw | ||
| /// elements and print that slice instead. | ||
| impl<E, T> Display for BitVec<E, T> | ||
| /// Give write access to all live elements in the underlying storage, including | ||
| /// the partially-filled tail. | ||
| impl<E, T> AsMut<[T]> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Render the `BitVec` contents for display. | ||
| /// Access the underlying store. | ||
| /// | ||
@@ -805,34 +591,18 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![BigEndian, u8; 0, 1, 0, 0, 1, 0, 1, 1, 0, 1]; | ||
| /// assert_eq!("01001011 01", &format!("{}", bv)); | ||
| /// let mut bv: BitVec = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1]; | ||
| /// for elt in bv.as_mut() { | ||
| /// *elt += 2; | ||
| /// } | ||
| /// assert_eq!(&[2, 0b1000_0010], bv.as_ref()); | ||
| /// ``` | ||
| fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
| self.fmt_body(fmt, false) | ||
| fn as_mut(&mut self) -> &mut [T] { | ||
| BitSlice::as_mut(self) | ||
| } | ||
| } | ||
| /// Ready the underlying storage for Drop. | ||
| impl<E, T> Drop for BitVec<E, T> | ||
| /// Give read access to all live elements in the underlying storage, including | ||
| /// the partially-filled tail. | ||
| impl<E, T> AsRef<[T]> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn drop(&mut self) { | ||
| // If the `Vec` is non-empty, set the length to the number of used | ||
| // elements as preparation for drop. The bits do not need to be wiped. | ||
| // | ||
| // If we don't do this, the `Vec` drop will treat the bit total as the | ||
| // number of elements and try to loop through all of them, which will | ||
| // not take 2 ** T::BITS times as long to run as expected, because | ||
| // it'll segfault. | ||
| let raw = self.raw_len(); | ||
| unsafe { self.inner.set_len(raw); } | ||
| } | ||
| } | ||
| /// Extend a `BitVec` with the contents of another bitstream. | ||
| /// | ||
| /// At present, this just calls `.push()` in a loop. When specialization becomes | ||
| /// available, it will be able to more intelligently perform bulk moves from the | ||
| /// source into `self` when the source is `BitSlice`-compatible. | ||
| impl<E, T> Extend<bool> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Extend a `BitVec` from another bitstream. | ||
| /// Access the underlying store. | ||
| /// | ||
@@ -843,17 +613,7 @@ /// # Examples | ||
| /// use bitvec::*; | ||
| /// let mut bv = bitvec![0; 4]; | ||
| /// bv.extend(bitvec![1; 4]); | ||
| /// assert_eq!("00001111", &format!("{}", bv)); | ||
| /// let bv = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1]; | ||
| /// assert_eq!(&[0, 0b1000_0000], bv.as_ref()); | ||
| /// ``` | ||
| fn extend<I>(&mut self, src: I) | ||
| where I: IntoIterator<Item=bool> { | ||
| let iter = src.into_iter(); | ||
| match iter.size_hint() { | ||
| (_, Some(hi)) => self.reserve(hi), | ||
| (lo, None) => self.reserve(lo), | ||
| } | ||
| for bit in iter { | ||
| self.push(bit); | ||
| } | ||
| self.shrink_to_fit(); | ||
| fn as_ref(&self) -> &[T] { | ||
| BitSlice::as_ref(self) | ||
| } | ||
@@ -1018,2 +778,114 @@ } | ||
| impl<E, T> Default for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn default() -> Self { | ||
| Self { | ||
| inner: Default::default(), | ||
| _endian: Default::default(), | ||
| } | ||
| } | ||
| } | ||
| /// Print the `BitVec` for debugging. | ||
| /// | ||
| /// The output is of the form `BitVec<E, T> [ELT, *]`, where `<E, T>` is the | ||
| /// endianness and element type, with square brackets on each end of the bits | ||
| /// and all the live elements in the vector printed in binary. The printout is | ||
| /// always in semantic order, and may not reflect the underlying store. To see | ||
| /// the underlying store, use `format!("{:?}", self.as_ref());` instead. | ||
| /// | ||
| /// The alternate character `{:#?}` prints each element on its own line, rather | ||
| /// than separated by a space. | ||
| impl<E, T> Debug for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Render the `BitVec` type header and contents for debug. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![LittleEndian, u16; | ||
| /// 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1 | ||
| /// ]; | ||
| /// assert_eq!( | ||
| /// "BitVec<LittleEndian, u16> [0101000011110101]", | ||
| /// &format!("{:?}", bv) | ||
| /// ); | ||
| /// ``` | ||
| fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
| let alt = fmt.alternate(); | ||
| self.fmt_header(fmt)?; | ||
| fmt.write_str(" [")?; | ||
| if alt { writeln!(fmt)?; } | ||
| self.fmt_body(fmt, true)?; | ||
| if alt { writeln!(fmt)?; } | ||
| fmt.write_str("]") | ||
| } | ||
| } | ||
| /// Print the `BitVec` for displaying. | ||
| /// | ||
| /// This prints each element in turn, formatted in binary in semantic order (so | ||
| /// the first bit seen is printed first and the last bit seen printed last). | ||
| /// Each element of storage is separated by a space for ease of reading. | ||
| /// | ||
| /// The alternate character `{:#}` prints each element on its own line. | ||
| /// | ||
| /// To see the in-memory representation, use `AsRef` to get access to the raw | ||
| /// elements and print that slice instead. | ||
| impl<E, T> Display for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Render the `BitVec` contents for display. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![BigEndian, u8; 0, 1, 0, 0, 1, 0, 1, 1, 0, 1]; | ||
| /// assert_eq!("01001011 01", &format!("{}", bv)); | ||
| /// ``` | ||
| fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
| self.fmt_body(fmt, false) | ||
| } | ||
| } | ||
| impl<E, T> Hash for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn hash<H>(&self, hasher: &mut H) | ||
| where H: Hasher { | ||
| BitSlice::<E, T>::hash(&self, hasher) | ||
| } | ||
| } | ||
| /// Extend a `BitVec` with the contents of another bitstream. | ||
| /// | ||
| /// At present, this just calls `.push()` in a loop. When specialization becomes | ||
| /// available, it will be able to more intelligently perform bulk moves from the | ||
| /// source into `self` when the source is `BitSlice`-compatible. | ||
| impl<E, T> Extend<bool> for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Extend a `BitVec` from another bitstream. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut bv = bitvec![0; 4]; | ||
| /// bv.extend(bitvec![1; 4]); | ||
| /// assert_eq!("00001111", &format!("{}", bv)); | ||
| /// ``` | ||
| fn extend<I>(&mut self, src: I) | ||
| where I: IntoIterator<Item=bool> { | ||
| let iter = src.into_iter(); | ||
| match iter.size_hint() { | ||
| (_, Some(hi)) => self.reserve(hi), | ||
| (lo, None) => self.reserve(lo), | ||
| } | ||
| for bit in iter { | ||
| self.push(bit); | ||
| } | ||
| self.shrink_to_fit(); | ||
| } | ||
| } | ||
| /// Permit the construction of a `BitVec` by using `.collect()` on an iterator | ||
@@ -1047,2 +919,392 @@ /// of `bool`. | ||
| /// Produce an iterator over all the bits in the vector. | ||
| /// | ||
| /// This iterator follows the ordering in the vector type, and implements | ||
| /// `ExactSizeIterator`, since `BitVec`s always know exactly how large they are, | ||
| /// and `DoubleEndedIterator`, since they have known ends. | ||
| impl<E, T> IntoIterator for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Item = bool; | ||
| #[doc(hidden)] | ||
| type IntoIter = IntoIter<E, T>; | ||
| /// Iterate over the vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![BigEndian, u8; 1, 1, 1, 1, 0, 0, 0, 0]; | ||
| /// let mut count = 0; | ||
| /// for bit in bv { | ||
| /// if bit { count += 1; } | ||
| /// } | ||
| /// assert_eq!(count, 4); | ||
| /// ``` | ||
| fn into_iter(self) -> Self::IntoIter { | ||
| Self::IntoIter::from(self) | ||
| } | ||
| } | ||
| /// Add two `BitVec`s together, zero-extending the shorter. | ||
| /// | ||
| /// `BitVec` addition works just like adding numbers longhand on paper. The | ||
| /// first bits in the `BitVec` are the highest, so addition works from right to | ||
| /// left, and the shorter `BitVec` is assumed to be extended to the left with | ||
| /// zero. | ||
| /// | ||
| /// The output `BitVec` may be one bit longer than the longer input, if addition | ||
| /// overflowed. | ||
| /// | ||
| /// Numeric arithmetic is provided on `BitVec` as a convenience. Serious numeric | ||
| /// computation on variable-length integers should use the `num_bigint` crate | ||
| /// instead, which is written specifically for that use case. `BitVec`s are not | ||
| /// intended for arithmetic, and `bitvec` makes no guarantees about sustained | ||
| /// correctness in arithmetic at this time. | ||
| impl<E, T> Add for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Output = Self; | ||
| /// Add two `BitVec`s. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 1, 0, 1]; | ||
| /// let b = bitvec![0, 0, 1, 1]; | ||
| /// let s = a + b; | ||
| /// assert_eq!(bitvec![1, 0, 0, 0], s); | ||
| /// ``` | ||
| /// | ||
| /// This example demonstrates the addition of differently-sized `BitVec`s, | ||
| /// and will overflow. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![1; 4]; | ||
| /// let b = bitvec![1; 1]; | ||
| /// let s = b + a; | ||
| /// assert_eq!(bitvec![1, 0, 0, 0, 0], s); | ||
| /// ``` | ||
| fn add(mut self, addend: Self) -> Self::Output { | ||
| self += addend; | ||
| self | ||
| } | ||
| } | ||
| /// Add another `BitVec` into `self`, zero-extending the shorter. | ||
| /// | ||
| /// `BitVec` addition works just like adding numbers longhand on paper. The | ||
| /// first bits in the `BitVec` are the highest, so addition works from right to | ||
| /// left, and the shorter `BitVec` is assumed to be extended to the left with | ||
| /// zero. | ||
| /// | ||
| /// The output `BitVec` may be one bit longer than the longer input, if addition | ||
| /// overflowed. | ||
| /// | ||
| /// Numeric arithmetic is provided on `BitVec` as a convenience. Serious numeric | ||
| /// computation on variable-length integers should use the `num_bigint` crate | ||
| /// instead, which is written specifically for that use case. `BitVec`s are not | ||
| /// intended for arithmetic, and `bitvec` makes no guarantees about sustained | ||
| /// correctness in arithmetic at this time. | ||
| impl<E, T> AddAssign for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Add another `BitVec` into `self`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut a = bitvec![1, 0, 0, 1]; | ||
| /// let b = bitvec![0, 1, 1, 1]; | ||
| /// a += b; | ||
| /// assert_eq!(a, bitvec![1, 0, 0, 0, 0]); | ||
| /// ``` | ||
| fn add_assign(&mut self, mut addend: Self) { | ||
| use std::iter::repeat; | ||
| // If the other vec is longer, swap them and try again. | ||
| if addend.len() > self.len() { | ||
| mem::swap(self, &mut addend); | ||
| return *self += addend; | ||
| } | ||
| // Now that self.len() >= addend.len(), proceed with addition. | ||
| // | ||
| // I don't, at this time, want to implement a carry-lookahead adder in | ||
| // software, so this is going to be a plain ripple-carry adder with | ||
| // O(n) runtime. Furthermore, until I think of an optimization | ||
| // strategy, it is going to build up another bitvec to use as a stack. | ||
| // | ||
| // Computers are fast. Whatever. | ||
| let mut c = false; | ||
| let mut stack = BitVec::<E, T>::with_capacity(self.len()); | ||
| // Reverse self, reverse addend and zero-extend, and zip both together. | ||
| // This walks both vecs from rightmost to leftmost, and considers an | ||
| // early expiration of addend to continue with 0 bits. | ||
| // | ||
| // 100111 | ||
| // + 0010 | ||
| // ^^---- semantically zero | ||
| for (a, b) in self.iter().rev().zip(addend.into_iter().rev().chain(repeat(false))) { | ||
| // Addition is a finite state machine that can be precomputed into a single | ||
| // jump table rather than requiring more complex branching. | ||
| // The table is indexed as (carry, a, b) and returns (bit, carry). | ||
| static JUMP: [u8; 8] = [ | ||
| // 0 + 0 + 0 = 0, 0 | ||
| 0, | ||
| // 0 + 1 + 0 = 1, 0 | ||
| 2, | ||
| // 1 + 0 + 0 = 1, 0 | ||
| 2, | ||
| // 1 + 1 + 1 = 0, 1 | ||
| 1, | ||
| // 0 + 0 + 1 = 1, 0 | ||
| 2, | ||
| // 0 + 1 + 0 = 0, 1 | ||
| 1, | ||
| // 1 + 0 + 0 = 0, 1 | ||
| 1, | ||
| // 1 + 1 + 1 = 1, 1 | ||
| 3, | ||
| ]; | ||
| let idx = ((c as u8) << 2) | ((a as u8) << 1) | (b as u8); | ||
| let yz = JUMP[idx as usize]; | ||
| let (y, z) = (yz & 2 != 0, yz & 1 != 0); | ||
| // Note: I checked in Godbolt, and the above comes out to ten | ||
| // simple instructions with the JUMP baked in as immediate values. | ||
| // The more semantically clear match statement does not optimize | ||
| // nearly as well. | ||
| stack.push(y); | ||
| c = z; | ||
| } | ||
| // If the carry made it to the end, push it. | ||
| if c { | ||
| stack.push(true); | ||
| } | ||
| // Unwind the stack into `self`. | ||
| self.clear(); | ||
| while let Some(bit) = stack.pop() { | ||
| self.push(bit); | ||
| } | ||
| } | ||
| } | ||
| /// Perform the Boolean AND operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitAnd<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// AND a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let and = lhs & rhs; | ||
| /// assert_eq!("0001", &format!("{}", and)); | ||
| /// ``` | ||
| fn bitand(mut self, rhs: I) -> Self::Output { | ||
| self &= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean AND operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitAndAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// AND another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src &= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0001", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitand_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) & other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Perform the Boolean OR operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitOr<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// OR a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let or = lhs | rhs; | ||
| /// assert_eq!("0111", &format!("{}", or)); | ||
| /// ``` | ||
| fn bitor(mut self, rhs: I) -> Self::Output { | ||
| self |= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean OR operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitOrAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// OR another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src |= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0111", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitor_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) | other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Perform the Boolean XOR operation between each element of a `BitVec` and | ||
| /// anything that can provide a stream of `bool` values (such as another | ||
| /// `BitVec`, or any `bool` generator of your choice). The `BitVec` emitted will | ||
| /// have the length of the shorter sequence of bits -- if one is longer than the | ||
| /// other, the extra bits will be ignored. | ||
| impl<E, T, I> BitXor<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| type Output = Self; | ||
| /// XOR a vector and a bitstream, producing a new vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let lhs = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// let rhs = bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// let xor = lhs ^ rhs; | ||
| /// assert_eq!("0110", &format!("{}", xor)); | ||
| /// ``` | ||
| fn bitxor(mut self, rhs: I) -> Self::Output { | ||
| self ^= rhs; | ||
| self | ||
| } | ||
| } | ||
| /// Perform the Boolean XOR operation in place on a `BitVec`, using a stream of | ||
| /// `bool` values as the other bit for each operation. If the other stream is | ||
| /// shorter than `self`, `self` will be truncated when the other stream expires. | ||
| impl<E, T, I> BitXorAssign<I> for BitVec<E, T> | ||
| where E: Endian, T: Bits, I: IntoIterator<Item=bool> { | ||
| /// XOR another bitstream into a vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut src = bitvec![BigEndian, u8; 0, 1, 0, 1]; | ||
| /// src ^= bitvec![BigEndian, u8; 0, 0, 1, 1]; | ||
| /// assert_eq!("0110", &format!("{}", src)); | ||
| /// ``` | ||
| fn bitxor_assign(&mut self, rhs: I) { | ||
| let mut len = 0; | ||
| for (idx, other) in (0 .. self.len()).zip(rhs.into_iter()) { | ||
| let val = self.get(idx) ^ other; | ||
| self.set(idx, val); | ||
| len += 1; | ||
| } | ||
| self.truncate(len); | ||
| } | ||
| } | ||
| /// Reborrow the `BitVec` as a `BitSlice`. | ||
| /// | ||
| /// This mimics the separation between `Vec<T>` and `[T]`. | ||
| impl<E, T> Deref for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Target = BitSlice<E, T>; | ||
| /// Dereference `&BitVec` down to `&BitSlice`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv: BitVec = bitvec![1; 4]; | ||
| /// let bref: &BitSlice = &bv; | ||
| /// assert!(bref.get(2)); | ||
| /// ``` | ||
| fn deref(&self) -> &Self::Target { | ||
| // `BitVec`'s representation of its inner `Vec` matches exactly the | ||
| // invariants of how `BitSlice` references must look. This is fine. | ||
| unsafe { mem::transmute(&self.inner as &[T]) } | ||
| } | ||
| } | ||
| /// Reborrow the `BitVec` as a `BitSlice`. | ||
| /// | ||
| /// This mimics the separation between `Vec<T>` and `[T]`. | ||
| impl<E, T> DerefMut for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Dereference `&mut BitVec` down to `&mut BitSlice`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let mut bv: BitVec = bitvec![0; 6]; | ||
| /// let bref: &mut BitSlice = &mut bv; | ||
| /// assert!(!bref.get(5)); | ||
| /// bref.set(5, true); | ||
| /// assert!(bref.get(5)); | ||
| /// ``` | ||
| fn deref_mut(&mut self) -> &mut Self::Target { | ||
| unsafe { mem::transmute(&mut self.inner as &mut [T]) } | ||
| } | ||
| } | ||
| /// Ready the underlying storage for Drop. | ||
| impl<E, T> Drop for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn drop(&mut self) { | ||
| // If the `Vec` is non-empty, set the length to the number of used | ||
| // elements as preparation for drop. The bits do not need to be wiped. | ||
| // | ||
| // If we don't do this, the `Vec` drop will treat the bit total as the | ||
| // number of elements and try to loop through all of them, which will | ||
| // not take 2 ** T::BITS times as long to run as expected, because | ||
| // it'll segfault. | ||
| let raw = self.raw_len(); | ||
| unsafe { self.inner.set_len(raw); } | ||
| } | ||
| } | ||
| /// Get the bit at a specific index. The index must be less than the length of | ||
@@ -1117,28 +1379,25 @@ /// the `BitVec`. | ||
| /// Produce an iterator over all the bits in the vector. | ||
| /// 2's-complement negation of a `BitVec`. | ||
| /// | ||
| /// This iterator follows the ordering in the vector type, and implements | ||
| /// `ExactSizeIterator`, since `BitVec`s always know exactly how large they are, | ||
| /// and `DoubleEndedIterator`, since they have known ends. | ||
| impl<E, T> IntoIterator for BitVec<E, T> | ||
| /// In 2's-complement, negation is defined as bit-inversion followed by adding | ||
| /// one. | ||
| /// | ||
| /// Numeric arithmetic is provided on `BitVec` as a convenience. Serious numeric | ||
| /// computation on variable-length integers should use the `num_bigint` crate | ||
| /// instead, which is written specifically for that use case. `BitVec`s are not | ||
| /// intended for arithmetic, and `bitvec` makes no guarantees about sustained | ||
| /// correctness in arithmetic at this time. | ||
| impl<E, T> Neg for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Item = bool; | ||
| #[doc(hidden)] | ||
| type IntoIter = IntoIter<E, T>; | ||
| type Output = Self; | ||
| /// Iterate over the vector. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let bv = bitvec![BigEndian, u8; 1, 1, 1, 1, 0, 0, 0, 0]; | ||
| /// let mut count = 0; | ||
| /// for bit in bv { | ||
| /// if bit { count += 1; } | ||
| /// } | ||
| /// assert_eq!(count, 4); | ||
| /// ``` | ||
| fn into_iter(self) -> Self::IntoIter { | ||
| Self::IntoIter::from(self) | ||
| fn neg(mut self) -> Self::Output { | ||
| // An empty vector does nothing. | ||
| // Negative zero is zero. Without this check, -[0+] becomes[10+1]. | ||
| if self.is_empty() || self.not_any() { | ||
| return self; | ||
| } | ||
| self = !self; | ||
| self += BitVec::<E, T>::from(&[true] as &[bool]); | ||
| self | ||
| } | ||
@@ -1177,63 +1436,2 @@ } | ||
| /// Test if two `BitVec`s are semantically — not bitwise — equal. | ||
| /// | ||
| /// It is valid to compare two vectors of different endianness or element types. | ||
| /// | ||
| /// The equality condition requires that they have the same number of stored | ||
| /// bits and that each pair of bits in semantic order are identical. | ||
| impl<A, B, C, D> PartialEq<BitVec<C, D>> for BitVec<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `==`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let l: BitVec<LittleEndian, u16> = bitvec![LittleEndian, u16; 0, 1, 0, 1]; | ||
| /// let r: BitVec<BigEndian, u32> = bitvec![BigEndian, u32; 0, 1, 0, 1]; | ||
| /// assert!(l == r); | ||
| /// ``` | ||
| fn eq(&self, rhs: &BitVec<C, D>) -> bool { | ||
| BitSlice::eq(&self, &rhs) | ||
| } | ||
| } | ||
| impl<E, T> Eq for BitVec<E, T> | ||
| where E: Endian, T: Bits {} | ||
| /// Compare two `BitVec`s by semantic — not bitwise — ordering. | ||
| /// | ||
| /// The comparison sorts by testing each index for one vector to have a set bit | ||
| /// where the other vector has an unset bit. If the vectors are different, the | ||
| /// vector with the set bit sorts greater than the vector with the unset bit. | ||
| /// | ||
| /// If one of the vectors is exhausted before they differ, the longer vector is | ||
| /// greater. | ||
| impl<A, B, C, D> PartialOrd<BitVec<C, D>> for BitVec<A, B> | ||
| where A: Endian, B: Bits, C: Endian, D: Bits { | ||
| /// Perform a comparison by `<` or `>`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 1, 0, 0]; | ||
| /// let b = bitvec![0, 1, 0, 1]; | ||
| /// let c = bitvec![0, 1, 0, 1, 1]; | ||
| /// assert!(a < b); | ||
| /// assert!(b < c); | ||
| /// ``` | ||
| fn partial_cmp(&self, rhs: &BitVec<C, D>) -> Option<Ordering> { | ||
| BitSlice::partial_cmp(&self, &rhs) | ||
| } | ||
| } | ||
| impl<E, T> Ord for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| fn cmp(&self, rhs: &Self) -> Ordering { | ||
| BitSlice::cmp(&self, &rhs) | ||
| } | ||
| } | ||
| __bitvec_shift!(u8, u16, u32, u64, i8, i16, i32, i64); | ||
@@ -1464,3 +1662,2 @@ | ||
| let old_len = self.len(); | ||
| // Implement `Extend` to make this more efficient | ||
| for _ in 0 .. shamt { | ||
@@ -1479,2 +1676,136 @@ self.push(false); | ||
| /// Subtract one `BitVec` from another assuming 2's-complement encoding. | ||
| /// | ||
| /// Subtraction is a more complex operation than addition. The bit-level work is | ||
| /// largely the same, but semantic distinctions must be made. Unlike addition, | ||
| /// which is commutative and tolerant of switching the order of the addends, | ||
| /// subtraction cannot swap the minuend (LHS) and subtrahend (RHS). | ||
| /// | ||
| /// Because of the properties of 2's-complement arithmetic, M - S is equivalent | ||
| /// to M + (!S + 1). Subtraction therefore bitflips the subtrahend and adds one. | ||
| /// This may, in a degenerate case, cause the subtrahend to increase in length. | ||
| /// | ||
| /// Once the subtrahend is stable, the minuend zero-extends its left side in | ||
| /// order to match the length of the subtrahend if needed (this is provided by | ||
| /// the `>>` operator). | ||
| /// | ||
| /// When the minuend is stable, the minuend and subtrahend are added together | ||
| /// by the `<BitVec as Add>` implementation. The output will be encoded in | ||
| /// 2's-complement, so a leading one means that the output is considered | ||
| /// negative. | ||
| /// | ||
| /// Interpreting the contents of a `BitVec` as an integer is beyond the scope of | ||
| /// this crate. | ||
| /// | ||
| /// Numeric arithmetic is provided on `BitVec` as a convenience. Serious numeric | ||
| /// computation on variable-length integers should use the `num_bigint` crate | ||
| /// instead, which is written specifically for that use case. `BitVec`s are not | ||
| /// intended for arithmetic, and `bitvec` makes no guarantees about sustained | ||
| /// correctness in arithmetic at this time. | ||
| impl<E, T> Sub for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| type Output = Self; | ||
| /// Subtract one `BitVec` from another. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// Minuend larger than subtrahend, positive difference. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![1, 0]; | ||
| /// let b = bitvec![ 1]; | ||
| /// let c = a - b; | ||
| /// assert_eq!(bitvec![0, 1], c); | ||
| /// ``` | ||
| /// | ||
| /// Minuend smaller than subtrahend, negative difference. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![ 1]; | ||
| /// let b = bitvec![1, 0]; | ||
| /// let c = a - b; | ||
| /// assert_eq!(bitvec![1, 1], c); | ||
| /// ``` | ||
| /// | ||
| /// Subtraction from self is correctly handled. | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![1; 4]; | ||
| /// let b = a.clone(); | ||
| /// let c = a - b; | ||
| /// assert!(c.not_any(), "{:?}", c); | ||
| /// ``` | ||
| fn sub(mut self, subtrahend: Self) -> Self::Output { | ||
| self -= subtrahend; | ||
| self | ||
| } | ||
| } | ||
| /// Subtract another `BitVec` from `self`, assuming 2's-complement encoding. | ||
| /// | ||
| /// The minuend is zero-extended, or the subtrahend sign-extended, as needed to | ||
| /// ensure that the vectors are the same width before subtraction occurs. | ||
| /// | ||
| /// The `Sub` trait has more documentation on the subtraction process. | ||
| /// | ||
| /// Numeric arithmetic is provided on `BitVec` as a convenience. Serious numeric | ||
| /// computation on variable-length integers should use the `num_bigint` crate | ||
| /// instead, which is written specifically for that use case. `BitVec`s are not | ||
| /// intended for arithmetic, and `bitvec` makes no guarantees about sustained | ||
| /// correctness in arithmetic at this time. | ||
| impl<E, T> SubAssign for BitVec<E, T> | ||
| where E: Endian, T: Bits { | ||
| /// Subtract another `BitVec` from `self`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// use bitvec::*; | ||
| /// let a = bitvec![0, 0, 0, 1]; | ||
| /// let b = bitvec![0, 0, 0, 0]; | ||
| /// let c = a - b; | ||
| /// assert_eq!(c, bitvec![0, 0, 0, 1]); | ||
| /// ``` | ||
| fn sub_assign(&mut self, mut subtrahend: Self) { | ||
| // Test for a zero subtrahend. Subtraction of zero is the identity | ||
| // function, and can exit immediately. | ||
| if subtrahend.not_any() { | ||
| return; | ||
| } | ||
| // Invert the subtrahend in preparation for addition | ||
| subtrahend = -subtrahend; | ||
| let (llen, rlen) = (self.len(), subtrahend.len()); | ||
| // If the subtrahend is longer than the minuend, 0-extend the minuend. | ||
| if rlen > llen { | ||
| let diff = rlen - llen; | ||
| *self >>= diff; | ||
| *self += subtrahend; | ||
| } | ||
| else { | ||
| // If the minuend is longer than the subtrahend, 1-extend the | ||
| // subtrahend. | ||
| if llen > rlen { | ||
| let diff = llen - rlen; | ||
| let sign = subtrahend.get(0); | ||
| subtrahend >>= diff; | ||
| // Implementing BitVec >> (usize, bool) would permit sign | ||
| // extension in fewer steps. | ||
| for idx in 0 .. diff { | ||
| subtrahend.set(idx, sign); | ||
| } | ||
| } | ||
| let old = self.len(); | ||
| *self += subtrahend; | ||
| // If the subtraction emitted a carry, remove it. | ||
| if self.len() > old { | ||
| *self <<= 1; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| /// Iterate over an owned `BitVec`. | ||
@@ -1481,0 +1812,0 @@ #[doc(hidden)] |
Sorry, the diff of this file is not supported yet