From e30791fe445cb57e0f8e83e486cb644ef2b17fa4 Mon Sep 17 00:00:00 2001 From: tuxmain Date: Sat, 29 Apr 2023 16:51:57 +0200 Subject: [PATCH] fix: align_skip --- src/lib.rs | 21 +++++++++++++---- src/test.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a5d5bf0..dbdca7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,7 @@ impl RingBuf { self.write_index = (self.write_index + 1) % self.data.len(); len += 1; } - if self.available + len < self.data.len() { + if self.available + len <= self.data.len() { self.available += len; } else { self.read_index = self.write_index; @@ -210,10 +210,21 @@ impl RingBuf { /// Skip a few elements to align the read index, returning the number of skipped elements. pub fn align_skip(&mut self, align: usize) -> usize { assert_eq!(self.data.len() % align, 0); - let skip = align - (self.read_index % align); - self.read_index = (self.read_index + skip) % self.data.len(); - self.available = self.available.saturating_sub(skip); - skip + if self.read_index % align != 0 { + let skip = align - (self.read_index % align); + self.read_index = (self.read_index + skip) % self.data.len(); + if skip <= self.available { + self.available -= skip; + skip + } else { + let available = self.available; + self.available = 0; + self.write_index = self.read_index; + available + } + } else { + 0 + } } } diff --git a/src/test.rs b/src/test.rs index 303478d..042af58 100644 --- a/src/test.rs +++ b/src/test.rs @@ -4,20 +4,31 @@ use rand::Rng; #[test] fn chunks_exact_mut_random() { - const MAX_APPEND_LEN: usize = 256; + const MAX_APPEND_LEN: usize = 1023; const CHUNK_SIZE: usize = 32; + const BUF_SIZE: usize = 1024; let mut rng = rand::thread_rng(); - let mut ringbuf = RingBuf::new(1024, 0_u32); + let mut ringbuf = RingBuf::new(BUF_SIZE, 0_u32); let mut current_value = 0; for _ in 0_u32..1024 { let append_len = rng.gen_range(0..MAX_APPEND_LEN); + let overwritten = append_len; + let available = ringbuf.available(); assert_eq!( ringbuf.push_from_iter_overflowing( current_value as u32..current_value as u32 + append_len as u32 ), append_len ); + assert_eq!((available + append_len).min(BUF_SIZE), ringbuf.available()); + dbg!(append_len); + dbg!(current_value); + if append_len + available > BUF_SIZE { + current_value += append_len - (BUF_SIZE - available); + } + dbg!(current_value); + ringbuf.align_skip(CHUNK_SIZE); for (j, chunk) in ringbuf.chunks_exact_mut(CHUNK_SIZE).enumerate() { assert_eq!(chunk.len(), CHUNK_SIZE); for (k, v) in chunk.iter().enumerate() { @@ -74,3 +85,55 @@ fn push_from_slice_overflowing() { ([4, 5, 6, 7, 8].as_slice(), [9, 10, 11].as_slice()) ); } + +#[test] +fn align_skip_basic() { + let mut ringbuf = RingBuf::new(8, 0_u32); + + assert_eq!(ringbuf.align_skip(4), 0); + assert_eq!(ringbuf.available(), 0); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 0); + + assert!(ringbuf.push(1)); + assert_eq!(ringbuf.align_skip(4), 0); + assert_eq!(ringbuf.available(), 1); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 1); + + assert!(ringbuf.push(1)); + assert_eq!(ringbuf.align_skip(4), 0); + assert_eq!(ringbuf.available(), 2); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 2); + + assert!(ringbuf.push(1)); + assert_eq!(ringbuf.align_skip(4), 0); + assert_eq!(ringbuf.available(), 3); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 3); + + assert!(ringbuf.push(1)); + assert_eq!(ringbuf.align_skip(4), 0); + assert_eq!(ringbuf.available(), 4); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 4); + + assert_eq!(ringbuf.read_first_one(), Some(&1)); + assert_eq!(ringbuf.align_skip(4), 3); + assert_eq!(ringbuf.available(), 0); + assert_eq!(ringbuf.read_index, 4); + assert_eq!(ringbuf.write_index, 4); +} + +#[test] +fn align_skip_overflow() { + let mut ringbuf = RingBuf::new(8, 0_u32); + + ringbuf.push_from_slice_overflowing(&[1, 2, 3, 4, 5, 6]); + assert_eq!(ringbuf.read_first_slices(5).0, &[1, 2, 3, 4, 5]); + assert_eq!(ringbuf.align_skip(4), 1); + assert_eq!(ringbuf.available(), 0); + assert_eq!(ringbuf.read_index, 0); + assert_eq!(ringbuf.write_index, 0); +}