From 91dacb9a8c9d71d3b04ebc37bf04ec65233cbfdd Mon Sep 17 00:00:00 2001 From: Jakob Hilf Date: Wed, 19 Aug 2026 16:00:59 +0200 Subject: [PATCH 1/2] Fix to Reader and Writer Seek impls. This avoids unintentional clearing of internal members on calling stream_pos. --- src/reader.rs | 40 ++++++++++++++++++++++++++++++++-------- src/writer.rs | 22 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index fe3217de4..ce79de105 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -48,14 +48,18 @@ impl Seek for Reader { #[cfg(feature = "logging")] log::trace!("seek: {pos:?}"); - // clear leftover - self.leftover = None; - - let new_pos = self.inner.seek(pos)?; - self.bits_read = usize::try_from(new_pos) - .unwrap_or(usize::MAX) - .saturating_mul(8); - Ok(new_pos) + if pos == SeekFrom::Current(0) { + self.inner.seek(pos) + } else { + // clear leftover + self.leftover = None; + + let new_pos = self.inner.seek(pos)?; + self.bits_read = usize::try_from(new_pos) + .unwrap_or(usize::MAX) + .saturating_mul(8); + Ok(new_pos) + } } } @@ -935,4 +939,24 @@ mod tests { Some(bitvec![u8, Msb0; 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0]) ); } + + #[cfg(all(feature = "alloc", feature = "bits"))] + #[test] + // Issue #678 + fn test_regression_stream_position() { + let input = vec![0x0F, 0xFF, 0xF0]; + let mut reader = Reader::new(Cursor::new(&input)); + + let first_bits = reader.read_bits(4, Order::Msb0).unwrap(); + assert_eq!(first_bits, Some(bitvec!(u8, Msb0; 0, 0, 0, 0))); + + let pos = reader.stream_position().unwrap(); + assert_eq!(pos, 1); + + let second_bits = reader.read_bits(16, Order::Msb0).unwrap(); + assert_eq!( + second_bits, + Some(bitvec![u8, Msb0; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + ); + } } diff --git a/src/writer.rs b/src/writer.rs index 0a6c64113..7892bec88 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -32,9 +32,9 @@ impl Seek for Writer { #[cfg(feature = "logging")] log::trace!("seek: {pos:?}"); - // clear leftover + // clear leftover if the position changes #[cfg(feature = "bits")] - { + if pos != SeekFrom::Current(0) { self.leftover.0.clear(); self.leftover.1 = Order::Msb0; } @@ -551,4 +551,22 @@ mod tests { writer.finalize().unwrap(); assert_eq!(out_buf.into_inner(), [0b1001_0101, 0b0000_1010]); } + + #[cfg(all(feature = "alloc", feature = "bits"))] + #[test] + // Issue #678 + fn test_regression_stream_position() { + let mut target = vec![]; + let mut writer = Writer::new(Cursor::new(&mut target)); + + writer.write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0).unwrap(); + + let pos = writer.stream_position().unwrap(); + assert_eq!(pos, 0); + + writer.write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0).unwrap(); + + writer.finalize().unwrap(); + assert_eq!(target, [0xFF]); + } } From fa5c7154b975e8aefeec8f9efe54e7c4128c8000 Mon Sep 17 00:00:00 2001 From: Jakob Hilf Date: Wed, 19 Aug 2026 21:42:21 +0200 Subject: [PATCH 2/2] Fixes to satisfy CI checks in the PR. --- src/reader.rs | 2 ++ src/writer.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index ce79de105..f074634f2 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -944,6 +944,8 @@ mod tests { #[test] // Issue #678 fn test_regression_stream_position() { + use alloc::vec; + let input = vec![0x0F, 0xFF, 0xF0]; let mut reader = Reader::new(Cursor::new(&input)); diff --git a/src/writer.rs b/src/writer.rs index 7892bec88..d743dbc45 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -559,12 +559,16 @@ mod tests { let mut target = vec![]; let mut writer = Writer::new(Cursor::new(&mut target)); - writer.write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0).unwrap(); + writer + .write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0) + .unwrap(); let pos = writer.stream_position().unwrap(); assert_eq!(pos, 0); - writer.write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0).unwrap(); + writer + .write_bits_order(&bitvec![u8, Msb0; 1, 1, 1, 1], Order::Msb0) + .unwrap(); writer.finalize().unwrap(); assert_eq!(target, [0xFF]);