diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3d293d4..a427559 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -54,7 +54,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [1.67.0, 1.68.0] + rust: [1.76.0, 1.77.0] timeout-minutes: 45 steps: - uses: actions/checkout@v5 diff --git a/Cargo.toml b/Cargo.toml index b5a88ef..e3feeac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ documentation = "https://docs.rs/bit-vec/" keywords = ["data-structures", "bitvec", "bitmask", "bitmap", "bit"] readme = "README.md" edition = "2021" -rust-version = "1.67" +rust-version = "1.71" [dependencies] borsh = { version = "1.5.5", default-features = false, features = ["derive"], optional = true } diff --git a/README.md b/README.md index d7eb919..0abd23d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![crates.io][crates.io shield]][crates.io link] [![Documentation][docs.rs badge]][docs.rs link] ![Rust CI][github ci badge] -![MSRV][rustc 1.67+] +![MSRV][rustc 1.71+]

[![Dependency Status][deps.rs status]][deps.rs link] @@ -21,8 +21,8 @@ [crates.io link]: https://crates.io/crates/bit-vec [docs.rs badge]: https://docs.rs/bit-vec/badge.svg?version=0.8.0 [docs.rs link]: https://docs.rs/bit-vec/0.8.0/bit_vec/ -[github ci badge]: https://github.com/contain-rs/bit-vec/workflows/Rust/badge.svg?branch=master -[rustc 1.67+]: https://img.shields.io/badge/rustc-1.67%2B-blue.svg +[github ci badge]: https://github.com/contain-rs/bit-vec/actions/workflows/rust.yml/badge.svg +[rustc 1.71+]: https://img.shields.io/badge/rustc-1.71%2B-blue.svg [deps.rs status]: https://deps.rs/crate/bit-vec/0.8.0/status.svg [deps.rs link]: https://deps.rs/crate/bit-vec/0.8.0 [shields.io download count]: https://img.shields.io/crates/d/bit-vec.svg diff --git a/benches/bench.rs b/benches/bench.rs index d5915d4..b78b934 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -42,6 +42,18 @@ fn bench_usize_small(b: &mut Bencher) { }); } +#[bench] +fn bench_to_bytes(b: &mut Bencher) { + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + let mut r = small_rng(); + for _ in 0..BENCH_BITS / 10 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); + } + b.iter(|| { + black_box(bit_vec.to_bytes()); + }); +} + #[bench] fn bench_bit_set_big_fixed(b: &mut Bencher) { let mut r = small_rng(); diff --git a/src/lib.rs b/src/lib.rs index ad32249..a49a88f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -826,7 +826,7 @@ impl BitVec { pub fn or(&mut self, other: &Self) -> bool { self.ensure_invariant(); debug_assert!(other.is_last_block_fixed()); - self.process(other, |w1, w2| (w1 | w2)) + self.process(other, |w1, w2| w1 | w2) } /// Calculates the bitwise `and` of two bitvectors. @@ -857,7 +857,7 @@ impl BitVec { pub fn and(&mut self, other: &Self) -> bool { self.ensure_invariant(); debug_assert!(other.is_last_block_fixed()); - self.process(other, |w1, w2| (w1 & w2)) + self.process(other, |w1, w2| w1 & w2) } /// Calculates the difference between two bitvectors. @@ -896,7 +896,7 @@ impl BitVec { pub fn difference(&mut self, other: &Self) -> bool { self.ensure_invariant(); debug_assert!(other.is_last_block_fixed()); - self.process(other, |w1, w2| (w1 & !w2)) + self.process(other, |w1, w2| w1 & !w2) } /// Calculates the xor of two bitvectors. @@ -927,7 +927,7 @@ impl BitVec { pub fn xor(&mut self, other: &Self) -> bool { self.ensure_invariant(); debug_assert!(other.is_last_block_fixed()); - self.process(other, |w1, w2| (w1 ^ w2)) + self.process(other, |w1, w2| w1 ^ w2) } /// Calculates the nand of two bitvectors. @@ -1322,30 +1322,35 @@ impl BitVec { /// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); /// ``` pub fn to_bytes(&self) -> Vec { + static REVERSE_TABLE: [u8; 256] = { + let mut tbl = [0u8; 256]; + let mut i: u8 = 0; + loop { + tbl[i as usize] = i.reverse_bits(); + if i == 255 { + break; + } + i += 1; + } + tbl + }; self.ensure_invariant(); - // Oh lord, we're mapping this to bytes bit-by-bit! - fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 { - let offset = byte * 8 + bit; - if offset >= bit_vec.nbits { - 0 - } else { - (bit_vec[offset] as u8) << (7 - bit) + + let len = self.nbits / 8 + if self.nbits % 8 == 0 { 0 } else { 1 }; + let mut result = Vec::with_capacity(len); + + for byte_idx in 0..len { + let mut byte = 0u8; + for bit_idx in 0..8 { + let offset = byte_idx * 8 + bit_idx; + if offset < self.nbits && self[offset] { + byte |= 1 << bit_idx; + } } + result.push(REVERSE_TABLE[byte as usize]); } - let len = self.nbits / 8 + if self.nbits % 8 == 0 { 0 } else { 1 }; - (0..len) - .map(|i| { - bit(self, i, 0) - | bit(self, i, 1) - | bit(self, i, 2) - | bit(self, i, 3) - | bit(self, i, 4) - | bit(self, i, 5) - | bit(self, i, 6) - | bit(self, i, 7) - }) - .collect() + result } /// Compares a `BitVec` to a slice of `bool`s.