Skip to content

Commit ba76deb

Browse files
writer: Remove one allocation (#430)
* Remove allocation and force bit.len() < MAX_BITS_AMT like reader does * Speed up deku_write_bits by 20% on my machine
1 parent 5799ff4 commit ba76deb

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

src/reader.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub enum ReaderRet {
1919
Bits(Option<BitVec<u8, Msb0>>),
2020
}
2121

22+
/// Max bits requested from [`Reader::read_bits`] during one call
23+
pub const MAX_BITS_AMT: usize = 128;
24+
2225
/// Reader to use with `from_reader_with_ctx`
2326
pub struct Reader<'a, R: Read> {
2427
inner: &'a mut R,
@@ -28,9 +31,6 @@ pub struct Reader<'a, R: Read> {
2831
pub bits_read: usize,
2932
}
3033

31-
/// Max bits requested from [`Reader::read_bits`] during one call
32-
pub const MAX_BITS_AMT: usize = 128;
33-
3434
impl<'a, R: Read> Reader<'a, R> {
3535
/// Create a new `Reader`
3636
#[inline]

src/writer.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const fn bits_of<T>() -> usize {
1313
core::mem::size_of::<T>().saturating_mul(<u8>::BITS as usize)
1414
}
1515

16+
/// Max bits written to [`Reader::write_bits`] during one call
17+
pub const MAX_BITS_AMT: usize = 128;
18+
1619
/// Container to use with `to_writer`
1720
pub struct Writer<W: Write> {
1821
pub(crate) inner: W,
@@ -43,6 +46,9 @@ impl<W: Write> Writer<W> {
4346
///
4447
/// Any leftover bits will be written before `bits`, and non-written bits will
4548
/// be stored in `self.leftover`.
49+
///
50+
/// # Params
51+
/// `bits` - Amount of bits that will be written. length must be <= [`MAX_BITS_AMT`].
4652
#[inline(never)]
4753
pub fn write_bits(&mut self, bits: &BitSlice<u8, Msb0>) -> Result<(), DekuError> {
4854
#[cfg(feature = "logging")]
@@ -66,7 +72,8 @@ impl<W: Write> Writer<W> {
6672
};
6773

6874
// one shot impl of BitSlice::read(no read_exact), but for no_std
69-
let mut buf = alloc::vec![0x00; bits.len() / 8];
75+
let mut buf = [0; MAX_BITS_AMT];
76+
let buf = &mut buf[..bits.len() / 8];
7077
let mut count = 0;
7178
bits.chunks_exact(bits_of::<u8>())
7279
.zip(buf.iter_mut())
@@ -81,7 +88,7 @@ impl<W: Write> Writer<W> {
8188
bits = unsafe { bits.get_unchecked(count * bits_of::<u8>()..) };
8289

8390
self.leftover = bits.to_bitvec();
84-
if self.inner.write_all(&buf).is_err() {
91+
if self.inner.write_all(buf).is_err() {
8592
return Err(DekuError::Write);
8693
}
8794

tests/test_alloc.rs

+15
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,19 @@ mod tests {
6363
(5, 0, 5)
6464
);
6565
}
66+
67+
#[test]
68+
#[cfg_attr(miri, ignore)]
69+
fn test_simple_write() {
70+
let input = hex!("aa_bbbb_cc_0102_dd_ffffff_aa_0100ff");
71+
let t = TestDeku::from_reader((&mut input.as_slice(), 0)).unwrap().1;
72+
73+
assert_eq!(
74+
count_alloc(|| {
75+
t.to_bytes().unwrap();
76+
})
77+
.0,
78+
(2, 1, 2)
79+
);
80+
}
6681
}

0 commit comments

Comments
 (0)