Sign In

bitvec

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitvec - cargo Package Compare versions

Comparing version
0.20.0
to
0.20.1
+21
LICENSE.txt
MIT License
Copyright (c) 2018 myrrlyn (Alexander Payne)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1
-1
{
"git": {
"sha1": "e9212ca992b9c21ea112b027520bc2a6128b2eaa"
"sha1": "9e3f80fb96f01ff7fe0a2f85ed678256d76d76ed"
}
}

@@ -21,2 +21,12 @@ # This file is automatically @generated by Cargo.

[[package]]
name = "bincode"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
dependencies = [
"byteorder",
"serde",
]
[[package]]
name = "bitflags"

@@ -29,4 +39,5 @@ version = "1.2.1"

name = "bitvec"
version = "0.20.0"
version = "0.20.1"
dependencies = [
"bincode",
"criterion",

@@ -33,0 +44,0 @@ "funty",

@@ -16,5 +16,5 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

name = "bitvec"
version = "0.20.0"
version = "0.20.1"
authors = ["myrrlyn <self@myrrlyn.dev>"]
include = ["Cargo.toml", "src/**/*.rs", "benches/*.rs"]
include = ["Cargo.toml", "LICENSE.txt", "src/**/*.rs", "benches/*.rs"]
description = "A crate for manipulating memory, bit by bit"

@@ -39,3 +39,3 @@ homepage = "https://myrrlyn.net/crates/bitvec"

[dependencies.radium]
version = "0.6"
version = "0.6.1"

@@ -53,2 +53,5 @@ [dependencies.serde]

default-features = false
[dev-dependencies.bincode]
version = "1.3"
[dev-dependencies.criterion]

@@ -55,0 +58,0 @@ version = "0.3"

@@ -149,3 +149,2 @@ /*! A statically-allocated, fixed-size, buffer containing a [`BitSlice`] region.

#[repr(transparent)]
#[derive(Copy)]
pub struct BitArray<O = Lsb0, V = [usize; 1]>

@@ -231,3 +230,3 @@ where

#[inline]
pub fn as_slice(&self) -> &[V::Store] {
pub fn as_raw_slice(&self) -> &[V::Store] {
unsafe {

@@ -243,3 +242,3 @@ slice::from_raw_parts(

#[inline]
pub fn as_mut_slice(&mut self) -> &mut [V::Store] {
pub fn as_mut_raw_slice(&mut self) -> &mut [V::Store] {
unsafe {

@@ -253,2 +252,18 @@ slice::from_raw_parts_mut(

#[doc(hidden)]
#[inline(always)]
#[cfg(not(tarpaulin_include))]
#[deprecated = "This is renamed to `as_raw_slice`"]
pub fn as_slice(&self) -> &[V::Store] {
self.as_raw_slice()
}
#[doc(hidden)]
#[inline(always)]
#[cfg(not(tarpaulin_include))]
#[deprecated = "This is renamed to `as_mut_raw_slice`"]
pub fn as_mut_slice(&mut self) -> &mut [V::Store] {
self.as_mut_raw_slice()
}
/// Views the interior buffer.

@@ -255,0 +270,0 @@ #[inline(always)]

@@ -120,3 +120,3 @@ //! Array iteration.

self.array
.as_slice()
.as_raw_slice()
.pipe(BitPtr::<Const, O, V::Store>::from_slice)

@@ -123,0 +123,0 @@ .add(index)

@@ -167,3 +167,3 @@ //! Port of the `[T; N]` operator implementations.

fn not(mut self) -> Self::Output {
for elem in self.as_mut_slice() {
for elem in self.as_mut_raw_slice() {
elem.store_value(!elem.load_value());

@@ -170,0 +170,0 @@ }

@@ -41,5 +41,5 @@ //! Unit tests for the `array` module.

let s: &mut [u8] = arr.as_mut_slice();
let s: &mut [u8] = arr.as_mut_raw_slice();
s[0] = !0u8;
let s: &[u8] = arr.as_slice();
let s: &[u8] = arr.as_raw_slice();
assert_eq!(s, &[!0, 0, 0]);

@@ -46,0 +46,0 @@

@@ -70,3 +70,5 @@ //! Non-operator trait implementations.

let mut out = Self::zeroed();
for (dst, src) in out.as_mut_slice().iter_mut().zip(self.as_slice()) {
for (dst, src) in
out.as_mut_raw_slice().iter_mut().zip(self.as_raw_slice())
{
dst.store_value(src.load_value());

@@ -381,2 +383,9 @@ }

impl<O, V> Copy for BitArray<O, V>
where
O: BitOrder,
V: BitView + Copy,
{
}
impl<O, V> Unpin for BitArray<O, V>

@@ -383,0 +392,0 @@ where

//! Internal support utilities.
use core::ops::{
Bound,
Range,
RangeBounds,
use crate::{
order::BitOrder,
store::BitStore,
};
use core::{
any::TypeId,
ops::{
Bound,
Range,
RangeBounds,
},
};
/** Normalizes any range into a basic `Range`.

@@ -32,2 +40,3 @@

**/
#[inline]
pub fn normalize_range<R>(bounds: R, end: usize) -> Range<usize>

@@ -62,2 +71,3 @@ where R: RangeBounds<usize> {

**/
#[inline]
pub fn assert_range(range: Range<usize>, end: impl Into<Option<usize>>) {

@@ -80,2 +90,28 @@ if range.start > range.end {

/// Tests if two `BitOrder` type parameters match each other.
///
/// This evaluates to a compile-time constant, and is removed during codegen.
#[inline(always)]
pub fn match_order<O1, O2>() -> bool
where
O1: BitOrder,
O2: BitOrder,
{
TypeId::of::<O1>() == TypeId::of::<O2>()
}
/// Tests if two `<O, T>` type parameter pairs match each other.
///
/// This evaluates to a compile-time constant, and is removed during codegen.
#[inline(always)]
pub fn match_types<O1, T1, O2, T2>() -> bool
where
O1: BitOrder,
T1: BitStore,
O2: BitOrder,
T2: BitStore,
{
match_order::<O1, O2>() && TypeId::of::<T1>() == TypeId::of::<T2>()
}
#[cfg(all(test, feature = "std"))]

@@ -82,0 +118,0 @@ mod tests {

@@ -410,2 +410,5 @@ /*! Batched load/store access to bitfields.

///
/// This example shows how a value is segmented across multiple storage
/// elements:
///
/// ```rust

@@ -435,2 +438,24 @@ /// use bitvec::prelude::*;

///
/// And this example shows how the same memory region will be read by
/// different `BitOrder` implementors:
///
/// ```rust
/// use bitvec::prelude::*;
///
/// // Bit pos: 14 19 16
/// // Lsb0: ─┤ ├──┤
/// let arr = [0b0100_0000_0000_0011u16, 0b0001_0000_0000_1110u16];
/// // Msb0: ├─ ├──┤
/// // Bit pos: 14 16 19
///
/// assert_eq!(
/// arr.view_bits::<Lsb0>()[14 .. 20].load_le::<u8>(),
/// 0b111001,
/// );
/// assert_eq!(
/// arr.view_bits::<Msb0>()[14 .. 20].load_le::<u8>(),
/// 0b000111,
/// );
/// ```
///
/// [`M::BITS`]: crate::mem::BitMemory::BITS

@@ -470,2 +495,5 @@ /// [`self.len()`]: crate::slice::BitSlice::len

///
/// This example shows how a value is segmented across multiple storage
/// elements:
///
/// ```rust

@@ -497,2 +525,23 @@ /// use bitvec::prelude::*;

///
/// And this example shows how the same memory region will be read by
/// different `BitOrder` implementations:
///
/// ```rust
/// use bitvec::prelude::*;
/// // Bit pos: 14 19 16
/// // Lsb0: ─┤ ├──┤
/// let arr = [0b0100_0000_0000_0011u16, 0b0001_0000_0000_1110u16];
/// // Msb0: ├─ ├──┤
/// // Bit pos: 14 15 19
///
/// assert_eq!(
/// arr.view_bits::<Lsb0>()[14 .. 20].load_be::<u8>(),
/// 0b011110,
/// );
/// assert_eq!(
/// arr.view_bits::<Msb0>()[14 .. 20].load_be::<u8>(),
/// 0b110001,
/// );
/// ```
///
/// [`M::BITS`]: crate::mem::BitMemory::BITS

@@ -534,2 +583,5 @@ /// [`self.len()`]: crate::slice::BitSlice::len

///
/// This example shows how a value is segmented across multiple storage
/// elements:
///
/// ```rust

@@ -559,2 +611,23 @@ /// use bitvec::prelude::*;

///
/// And this example shows how the same memory region is written by
/// different `BitOrder` implementations:
///
/// ```rust
/// use bitvec::prelude::*;
/// let mut lsb0 = bitarr![Lsb0, u16; 0; 32];
/// let mut msb0 = bitarr![Msb0, u16; 0; 32];
///
/// // Bit pos: 14 19 16
/// // Lsb0: ─┤ ├──┤
/// let exp_lsb0 = [0b0100_0000_0000_0000u16, 0b0000_0000_0000_1110u16];
/// let exp_msb0 = [0b0000_0000_0000_0011u16, 0b0001_0000_0000_0000u16];
/// // Msb0: ├─ ├──┤
/// // Bit pos: 14 15 19
///
/// lsb0[14 ..= 19].store_le(0b111001u8);
/// msb0[14 ..= 19].store_le(0b000111u8);
/// assert_eq!(lsb0.as_raw_slice(), exp_lsb0);
/// assert_eq!(msb0.as_raw_slice(), exp_msb0);
/// ```
///
/// [`M::BITS`]: crate::mem::BitMemory::BITS

@@ -596,2 +669,5 @@ /// [`self.len()`]: crate::slice::BitSlice::len

///
/// This example shows how a value is segmented across multiple storage
/// elements:
///
/// ```rust

@@ -621,2 +697,23 @@ /// use bitvec::prelude::*;

///
/// And this example shows how the same memory region is written by
/// different `BitOrder` implementations:
///
/// ```rust
/// use bitvec::prelude::*;
/// let mut lsb0 = bitarr![Lsb0, u16; 0; 32];
/// let mut msb0 = bitarr![Msb0, u16; 0; 32];
///
/// // Bit pos: 14 19 16
/// // Lsb0: ─┤ ├──┤
/// let exp_lsb0 = [0b0100_0000_0000_0000u16, 0b0000_0000_0000_1110u16];
/// let exp_msb0 = [0b0000_0000_0000_0011u16, 0b0001_0000_0000_0000u16];
/// // Msb0: ├─ ├──┤
/// // Bit pos: 14 15 19
///
/// lsb0[14 ..= 19].store_be(0b011110u8);
/// msb0[14 ..= 19].store_be(0b110001u8);
/// assert_eq!(lsb0.as_raw_slice(), exp_lsb0);
/// assert_eq!(msb0.as_raw_slice(), exp_msb0);
/// ```
///
/// [`M::BITS`]: crate::mem::BitMemory::BITS

@@ -720,3 +817,8 @@ /// [`self.len()`]: crate::slice::BitSlice::len

let shamt = head.value();
accum <<= T::Mem::BITS - shamt;
if M::BITS > T::Mem::BITS - shamt {
accum <<= T::Mem::BITS - shamt;
}
else {
accum = M::ZERO;
}
accum |= get::<T, M>(elem, Lsb0::mask(head, None), shamt);

@@ -799,5 +901,9 @@ }

if let Some((elem, tail)) = tail {
// If the tail is at the limit, then none of the above
// branches entered, and the shift would fail. Clamp to 0.
accum <<= tail.value() & M::MASK;
let shamt = tail.value();
if M::BITS > shamt {
accum <<= shamt;
}
else {
accum = M::ZERO;
}
accum |= get::<T, M>(elem, Lsb0::mask(None, tail), 0);

@@ -848,3 +954,8 @@ }

set::<T, M>(elem, value, Lsb0::mask(head, None), shamt);
value >>= T::Mem::BITS - shamt;
if M::BITS > T::Mem::BITS - shamt {
value >>= T::Mem::BITS - shamt;
}
else {
value = M::ZERO;
}
}

@@ -902,5 +1013,9 @@

set::<T, M>(elem, value, Lsb0::mask(None, tail), 0);
// If the tail is at the limit, then none of the below
// branches will enter, and the shift will fail. Clamp to 0
value >>= tail.value() & M::MASK;
let shamt = tail.value();
if M::BITS > shamt {
value >>= shamt;
}
else {
value = M::ZERO;
}
}

@@ -1005,3 +1120,9 @@

if let Some((head, elem)) = head {
accum <<= T::Mem::BITS - head.value();
let shamt = T::Mem::BITS - head.value();
if M::BITS > shamt {
accum <<= shamt;
}
else {
accum = M::ZERO;
}
accum |= get::<T, M>(elem, Msb0::mask(head, None), 0);

@@ -1085,8 +1206,13 @@ }

if let Some((elem, tail)) = tail {
let width = tail.value();
accum <<= width;
let shamt = tail.value();
if M::BITS > shamt {
accum <<= shamt;
}
else {
accum = M::ZERO;
}
accum |= get::<T, M>(
elem,
Msb0::mask(None, tail),
T::Mem::BITS - width,
T::Mem::BITS - shamt,
);

@@ -1139,3 +1265,9 @@ }

set::<T, M>(elem, value, Msb0::mask(head, None), 0);
value >>= T::Mem::BITS - head.value();
let shamt = T::Mem::BITS - head.value();
if M::BITS > shamt {
value >>= shamt;
}
else {
value = M::ZERO;
}
}

@@ -1206,3 +1338,8 @@

);
value >>= tail.value();
if M::BITS > tail.value() {
value >>= tail.value();
}
else {
value = M::ZERO;
}
}

@@ -1209,0 +1346,0 @@

@@ -103,2 +103,61 @@ //! Unit tests for the `field` module.

#[test]
fn narrow_byte_fields() {
let mut data = [0u16; 2];
data.view_bits_mut::<Msb0>()[16 .. 24].store_be(0x12u8);
assert_eq!(data, [0x0000, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[16 .. 24].load_be::<u8>(), 0x12);
data.view_bits_mut::<Msb0>()[8 .. 16].store_be(0x34u8);
assert_eq!(data, [0x0034, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[8 .. 16].load_be::<u8>(), 0x34);
data.view_bits_mut::<Msb0>()[0 .. 8].store_be(0x56u8);
assert_eq!(data, [0x5634, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[0 .. 8].load_be::<u8>(), 0x56);
data = [0; 2];
data.view_bits_mut::<Msb0>()[16 .. 24].store_le(0x12u8);
assert_eq!(data, [0x0000, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[16 .. 24].load_le::<u8>(), 0x12);
data.view_bits_mut::<Msb0>()[8 .. 16].store_le(0x34u8);
assert_eq!(data, [0x0034, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[8 .. 16].load_le::<u8>(), 0x34);
data.view_bits_mut::<Msb0>()[0 .. 8].store_le(0x56u8);
assert_eq!(data, [0x5634, 0x1200]);
assert_eq!(data.view_bits::<Msb0>()[0 .. 8].load_le::<u8>(), 0x56);
data = [0; 2];
data.view_bits_mut::<Lsb0>()[16 .. 24].store_be(0x12u8);
assert_eq!(data, [0x0000, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[16 .. 24].load_be::<u8>(), 0x12);
data.view_bits_mut::<Lsb0>()[8 .. 16].store_be(0x34u8);
assert_eq!(data, [0x3400, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[8 .. 16].load_be::<u8>(), 0x34);
data.view_bits_mut::<Lsb0>()[0 .. 8].store_be(0x56u8);
assert_eq!(data, [0x3456, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[0 .. 8].load_be::<u8>(), 0x56);
data = [0; 2];
data.view_bits_mut::<Lsb0>()[16 .. 24].store_le(0x12u8);
assert_eq!(data, [0x0000, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[16 .. 24].load_le::<u8>(), 0x12);
data.view_bits_mut::<Lsb0>()[8 .. 16].store_le(0x34u8);
assert_eq!(data, [0x3400, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[8 .. 16].load_le::<u8>(), 0x34);
data.view_bits_mut::<Lsb0>()[0 .. 8].store_le(0x56u8);
assert_eq!(data, [0x3456, 0x0012]);
assert_eq!(data.view_bits::<Lsb0>()[0 .. 8].load_le::<u8>(), 0x56);
}
#[test]
fn wide_load() {

@@ -105,0 +164,0 @@ let mut data = bitarr![Lsb0, u16; 0; 256];

@@ -579,3 +579,3 @@ /*! Well-typed counters and register descriptors.

/// The inclusive maximum tail within an element `R`.
pub(crate) const LAST: Self = Self {
pub const LAST: Self = Self {
end: R::BITS,

@@ -585,3 +585,3 @@ _ty: PhantomData,

/// The inclusive minimum tail within an element `R`.
pub(crate) const ZERO: Self = Self {
pub const ZERO: Self = Self {
end: 0,

@@ -588,0 +588,0 @@ _ty: PhantomData,

@@ -21,2 +21,6 @@ /*! [`serde`]-powered de/serialization.

The exact implementation of the `serde` interfaces is considered an internal
detail and is not guaranteed; however, as it is technically public ABI, it will
only be modified in a major release (`0.X.n` to `0.Y.0` or `X.m.n` to `Y.0.0`).
[`BitArray`]: crate::array::BitArray

@@ -120,16 +124,16 @@ [`BitBox`]: crate::boxed::BitBox

/// Serializes the interior storage type directly, rather than routing through a
/// dynamic sequence serializer.
#[cfg(not(tarpaulin_include))]
impl<O, V> Serialize for BitArray<O, V>
where
O: BitOrder,
V: BitView,
<V::Store as BitStore>::Mem: Serialize,
V: BitView + Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
let ary = self.as_slice();
let mut state = serializer.serialize_seq(Some(ary.len()))?;
for elem in ary.iter().map(BitStore::load_value) {
state.serialize_element(&elem)?;
}
state.end()
unsafe { core::ptr::read(self) }
.value()
.serialize(serializer)
}

@@ -136,0 +140,0 @@ }

@@ -13,5 +13,7 @@ /*! Specialization overrides.

devel as dvl,
domain::Domain,
field::BitField,
mem::BitMemory,
order::{
BitOrder,
Lsb0,

@@ -26,2 +28,4 @@ Msb0,

use funty::IsInteger;
/** Order-specialized function implementations.

@@ -119,2 +123,196 @@

}
/// Seeks the index of the first `1` bit in the bit-slice.
pub(crate) fn sp_iter_ones_first(&self) -> Option<usize> {
let mut accum = 0;
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Lsb0::mask(head, tail) & elem.load_value()).value();
if val != T::Mem::ZERO {
accum +=
val.trailing_zeros() as usize - head.value() as usize;
return Some(accum);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((head, elem)) = head {
let val =
(Lsb0::mask(head, None) & elem.load_value()).value();
accum +=
val.trailing_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
for elem in body {
let val = elem.load_value();
accum += val.trailing_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
if let Some((elem, tail)) = tail {
let val =
(Lsb0::mask(None, tail) & elem.load_value()).value();
if val != T::Mem::ZERO {
accum += val.trailing_zeros() as usize;
return Some(accum);
}
}
None
},
}
}
/// Seeks the index of the last `1` bit in the bit-slice.
pub(crate) fn sp_iter_ones_last(&self) -> Option<usize> {
let mut out = match self.len() {
0 => return None,
n => n - 1,
};
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Lsb0::mask(head, tail) & elem.load_value()).value();
let dead_bits = T::Mem::BITS - tail.value();
if val != T::Mem::ZERO {
out -= val.leading_zeros() as usize - dead_bits as usize;
return Some(out);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((elem, tail)) = tail {
let val =
(Lsb0::mask(None, tail) & elem.load_value()).value();
let dead_bits =
T::Mem::BITS as usize - tail.value() as usize;
out -= val.leading_zeros() as usize - dead_bits;
if val != T::Mem::ZERO {
return Some(out);
}
}
for elem in body.iter().rev() {
let val = elem.load_value();
out -= val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(out);
}
}
if let Some((head, elem)) = head {
let val =
(Lsb0::mask(head, None) & elem.load_value()).value();
if val != T::Mem::ZERO {
out -= val.leading_zeros() as usize;
return Some(out);
}
}
None
},
}
}
/// Seeks the index of the first `0` bit in the bit-slice.
pub(crate) fn sp_iter_zeros_first(&self) -> Option<usize> {
let mut accum = 0;
match self.domain() {
Domain::Enclave { head, elem, tail } => {
// Load, invert, then mask and search for `1`.
let val = (Lsb0::mask(head, tail) & !elem.load_value()).value();
accum += val.trailing_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((head, elem)) = head {
let val =
(Lsb0::mask(head, None) & !elem.load_value()).value();
accum +=
val.trailing_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
for elem in body {
let val = !elem.load_value();
accum += val.trailing_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
if let Some((elem, tail)) = tail {
let val =
(Lsb0::mask(None, tail) & !elem.load_value()).value();
accum += val.trailing_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
None
},
}
}
/// Seeks the index of the last `0` bit in the bit-slice.
pub(crate) fn sp_iter_zeros_last(&self) -> Option<usize> {
let mut out = match self.len() {
0 => return None,
n => n - 1,
};
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Lsb0::mask(head, tail) & !elem.load_value()).value();
let dead_bits = T::Mem::BITS - tail.value();
if val != T::Mem::ZERO {
out -= val.leading_zeros() as usize - dead_bits as usize;
return Some(out);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((elem, tail)) = tail {
let val =
(Lsb0::mask(None, tail) & !elem.load_value()).value();
let dead_bits =
T::Mem::BITS as usize - tail.value() as usize;
out -= val.leading_zeros() as usize - dead_bits;
if val != T::Mem::ZERO {
return Some(out);
}
}
for elem in body.iter().rev() {
let val = !elem.load_value();
out -= val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(out);
}
}
if let Some((head, elem)) = head {
let val =
(Lsb0::mask(head, None) & !elem.load_value()).value();
if val != T::Mem::ZERO {
out -= val.leading_zeros() as usize;
return Some(out);
}
}
None
},
}
}
}

@@ -196,2 +394,195 @@

}
/// Seeks the index of the first `1` bit in the bit-slice.
pub(crate) fn sp_iter_ones_first(&self) -> Option<usize> {
let mut accum = 0;
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Msb0::mask(head, tail) & elem.load_value()).value();
accum += val.leading_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((head, elem)) = head {
let val =
(Msb0::mask(head, None) & elem.load_value()).value();
accum +=
val.leading_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
for elem in body {
let val = elem.load_value();
accum += val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
if let Some((elem, tail)) = tail {
let val =
(Msb0::mask(None, tail) & elem.load_value()).value();
accum += val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
None
},
}
}
/// Seeks the index of the last `1` bit in the bit-slice.
pub(crate) fn sp_iter_ones_last(&self) -> Option<usize> {
// Set the state tracker to the last live index in the bit-slice.
let mut out = match self.len() {
0 => return None,
n => n - 1,
};
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Msb0::mask(head, tail) & elem.load_value()).value();
let dead_bits = T::Mem::BITS - tail.value();
if val != T::Mem::ZERO {
out -= val.trailing_zeros() as usize - dead_bits as usize;
return Some(out);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((elem, tail)) = tail {
let val =
(Msb0::mask(None, tail) & elem.load_value()).value();
let dead_bits =
T::Mem::BITS as usize - tail.value() as usize;
out -= val.trailing_zeros() as usize - dead_bits;
if val != T::Mem::ZERO {
return Some(out);
}
}
for elem in body.iter().rev() {
let val = elem.load_value();
out -= val.trailing_zeros() as usize;
if val != T::Mem::ZERO {
return Some(out);
}
}
if let Some((head, elem)) = head {
let val =
(Msb0::mask(head, None) & elem.load_value()).value();
if val != T::Mem::ZERO {
out -= val.trailing_zeros() as usize;
return Some(out);
}
}
None
},
}
}
/// Seeks the index of the first `0` bit in the bit-slice.
pub(crate) fn sp_iter_zeros_first(&self) -> Option<usize> {
let mut accum = 0;
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Msb0::mask(head, tail) & !elem.load_value()).value();
accum += val.leading_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((head, elem)) = head {
let val =
(Msb0::mask(head, None) & !elem.load_value()).value();
accum +=
val.leading_zeros() as usize - head.value() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
for elem in body {
let val = !elem.load_value();
accum += val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
if let Some((elem, tail)) = tail {
let val =
(Msb0::mask(None, tail) & !elem.load_value()).value();
accum += val.leading_zeros() as usize;
if val != T::Mem::ZERO {
return Some(accum);
}
}
None
},
}
}
/// Seeks the index of the last `0` bit in the bit-slice.
pub(crate) fn sp_iter_zeros_last(&self) -> Option<usize> {
let mut out = match self.len() {
0 => return None,
n => n - 1,
};
match self.domain() {
Domain::Enclave { head, elem, tail } => {
let val = (Msb0::mask(head, tail) & !elem.load_value()).value();
let dead_bits = T::Mem::BITS - tail.value();
if val != T::Mem::ZERO {
out -= val.trailing_zeros() as usize - dead_bits as usize;
return Some(out);
}
None
},
Domain::Region { head, body, tail } => {
if let Some((elem, tail)) = tail {
let val =
(Msb0::mask(None, tail) & !elem.load_value()).value();
let dead_bits =
T::Mem::BITS as usize - tail.value() as usize;
out -= val.trailing_zeros() as usize - dead_bits;
if val != T::Mem::ZERO {
return Some(out);
}
}
for elem in body.iter().rev() {
let val = !elem.load_value();
out -= val.trailing_zeros() as usize;
if val != T::Mem::ZERO {
return Some(out);
}
}
if let Some((head, elem)) = head {
let val =
(Msb0::mask(head, None) & !elem.load_value()).value();
if val != T::Mem::ZERO {
out -= val.trailing_zeros() as usize;
return Some(out);
}
}
None
},
}
}
}

@@ -777,2 +777,89 @@ //! Unit tests for the `slice` module.

#[test]
fn specialized_iter_ones() {
let data = [0x08u8, 0x20, 0, 0x04, 0x08];
let bits = data.view_bits::<Msb0>();
assert!(bits[17 .. 23].sp_iter_ones_first().is_none());
assert!(bits[17 .. 23].sp_iter_ones_last().is_none());
assert!(bits[12 .. 28].sp_iter_ones_first().is_none());
assert!(bits[12 .. 28].sp_iter_ones_last().is_none());
assert_eq!(bits[3 ..].sp_iter_ones_first(), Some(1));
assert_eq!(bits[5 ..].sp_iter_ones_first(), Some(5));
assert_eq!(bits[11 ..].sp_iter_ones_first(), Some(18));
assert_eq!(bits[30 .. 38].sp_iter_ones_first(), Some(6));
assert_eq!(bits[34 .. 38].sp_iter_ones_first(), Some(2));
assert_eq!(bits[.. 38].sp_iter_ones_last(), Some(36));
assert_eq!(bits[.. 36].sp_iter_ones_last(), Some(29));
assert_eq!(bits[.. 29].sp_iter_ones_last(), Some(10));
assert_eq!(bits[2 .. 10].sp_iter_ones_last(), Some(2));
assert_eq!(bits[2 .. 6].sp_iter_ones_last(), Some(2));
let bits = data.view_bits::<Lsb0>();
assert!(bits[17 .. 23].sp_iter_ones_first().is_none());
assert!(bits[17 .. 23].sp_iter_ones_last().is_none());
assert!(bits[14 .. 26].sp_iter_ones_first().is_none());
assert!(bits[14 .. 26].sp_iter_ones_last().is_none());
assert_eq!(bits[2 ..].sp_iter_ones_first(), Some(1));
assert_eq!(bits[4 ..].sp_iter_ones_first(), Some(9));
assert_eq!(bits[14 ..].sp_iter_ones_first(), Some(12));
assert_eq!(bits[27 .. 38].sp_iter_ones_first(), Some(8));
assert_eq!(bits[34 .. 38].sp_iter_ones_first(), Some(1));
assert_eq!(bits[.. 38].sp_iter_ones_last(), Some(35));
assert_eq!(bits[.. 35].sp_iter_ones_last(), Some(26));
assert_eq!(bits[.. 26].sp_iter_ones_last(), Some(13));
assert_eq!(bits[2 .. 13].sp_iter_ones_last(), Some(1));
assert_eq!(bits[2 .. 6].sp_iter_ones_last(), Some(1));
}
#[test]
fn specialized_iter_zeros() {
let data = [!0x08u8, !0x20, !0, !0x04, !0x08];
let bits = data.view_bits::<Msb0>();
assert!(bits[17 .. 23].sp_iter_zeros_first().is_none());
assert!(bits[17 .. 23].sp_iter_zeros_last().is_none());
assert!(bits[12 .. 28].sp_iter_zeros_first().is_none());
assert!(bits[12 .. 28].sp_iter_zeros_last().is_none());
assert_eq!(
bits[3 ..].sp_iter_zeros_first(),
Some(1),
"{:b}",
&bits[3 ..]
);
assert_eq!(bits[5 ..].sp_iter_zeros_first(), Some(5));
assert_eq!(bits[11 ..].sp_iter_zeros_first(), Some(18));
assert_eq!(bits[30 .. 38].sp_iter_zeros_first(), Some(6));
assert_eq!(bits[34 .. 38].sp_iter_zeros_first(), Some(2));
assert_eq!(bits[.. 38].sp_iter_zeros_last(), Some(36));
assert_eq!(bits[.. 36].sp_iter_zeros_last(), Some(29));
assert_eq!(bits[.. 29].sp_iter_zeros_last(), Some(10));
assert_eq!(bits[2 .. 10].sp_iter_zeros_last(), Some(2));
assert_eq!(bits[2 .. 6].sp_iter_zeros_last(), Some(2));
let bits = data.view_bits::<Lsb0>();
assert!(bits[17 .. 23].sp_iter_zeros_first().is_none());
assert!(bits[17 .. 23].sp_iter_zeros_last().is_none());
assert!(bits[14 .. 26].sp_iter_zeros_first().is_none());
assert!(bits[14 .. 26].sp_iter_zeros_last().is_none());
assert_eq!(bits[2 ..].sp_iter_zeros_first(), Some(1));
assert_eq!(bits[4 ..].sp_iter_zeros_first(), Some(9));
assert_eq!(bits[14 ..].sp_iter_zeros_first(), Some(12));
assert_eq!(bits[27 .. 38].sp_iter_zeros_first(), Some(8));
assert_eq!(bits[34 .. 38].sp_iter_zeros_first(), Some(1));
assert_eq!(bits[.. 38].sp_iter_zeros_last(), Some(35));
assert_eq!(bits[.. 35].sp_iter_zeros_last(), Some(26));
assert_eq!(bits[.. 26].sp_iter_zeros_last(), Some(13));
assert_eq!(bits[2 .. 13].sp_iter_zeros_last(), Some(1));
assert_eq!(bits[2 .. 6].sp_iter_zeros_last(), Some(1));
}
#[cfg(feature = "alloc")]

@@ -779,0 +866,0 @@ mod format {

@@ -1013,9 +1013,10 @@ /*! A dynamically-allocated buffer containing a [`BitSlice`] region.

let elts = bitspan.elements();
let tail = head.value() as usize + new_len;
if let Some(extra) = tail.pipe(crate::mem::elts::<T>).checked_sub(elts) {
self.with_vec(|vec| func(&mut **vec, extra));
let capa = self.capacity();
// Zero the newly-reserved buffer.
unsafe { self.get_unchecked_mut(len .. capa) }.set_all(false);
}
let new_elts = crate::mem::elts::<T>(head.value() as usize + new_len);
let extra = new_elts - elts;
self.with_vec(|vec| {
func(&mut **vec, extra);
// Initialize any newly-allocated elements to zero, without
// initializing leftover dead capacity.
vec.resize_with(new_elts, || unsafe { mem::zeroed() });
});
}

@@ -1022,0 +1023,0 @@

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