From 60841ec34ce45664338ee96350d4cd48241a22aa Mon Sep 17 00:00:00 2001 From: tuxmain Date: Sat, 1 Oct 2022 10:10:23 +0200 Subject: [PATCH] Checked push --- README.md | 3 +-- src/lib.rs | 31 +++++++++++++++++++++++++++++-- src/test.rs | 14 ++++++++------ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1b1dd5e..de9db76 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,7 @@ Yet another Rust ring buffer implementation. **Early development**: more features will be added soon. Also, more tests. And probably breaking changes. Features: -* Push element -* Push from iterator +* Checked/unchecked element/iterator safe push * Mutable exact chunk iterator (read contiguous slices) ## License diff --git a/src/lib.rs b/src/lib.rs index 3a69b96..ec44407 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,13 +21,39 @@ impl RingBuf { } } - pub fn push(&mut self, value: T) { + pub fn push(&mut self, value: T) -> bool { + if self.available < self.data.len() { + self.data[self.write_index] = value; + self.write_index = (self.write_index + 1) % self.data.len(); + self.available = (self.available + 1).min(self.data.len()); + true + } else { + false + } + } + + pub fn push_unchecked(&mut self, value: T) { self.data[self.write_index] = value; self.write_index = (self.write_index + 1) % self.data.len(); self.available = (self.available + 1).min(self.data.len()); } - pub fn push_from_iter>(&mut self, iter: I) { + pub fn push_from_iter>(&mut self, mut iter: I) -> usize { + let mut len = 0; + while len < self.data.len() - self.available { + if let Some(value) = iter.next() { + self.data[self.write_index] = value; + self.write_index = (self.write_index + 1) % self.data.len(); + len += 1; + } else { + break; + } + } + self.available += len; + len + } + + pub fn push_from_iter_unchecked>(&mut self, iter: I) -> usize { let mut len = 0; for value in iter { self.data[self.write_index] = value; @@ -35,6 +61,7 @@ impl RingBuf { len += 1; } self.available = (self.available + len).min(self.data.len()); + len } pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut { diff --git a/src/test.rs b/src/test.rs index dd2d0ab..d3a7b90 100644 --- a/src/test.rs +++ b/src/test.rs @@ -9,11 +9,13 @@ fn correctness_random() { let mut rng = rand::thread_rng(); let mut ringbuf = RingBuf::new(1024, 0_u32); - let mut buf = [0; 32]; let mut current_value = 0; for _ in 0_u32..1024 { let append_len = rng.gen_range(0..MAX_APPEND_LEN); - ringbuf.push_from_iter(current_value as u32..current_value as u32 + append_len as u32); + assert_eq!( + ringbuf.push_from_iter(current_value as u32..current_value as u32 + append_len as u32), + append_len + ); for (j, chunk) in ringbuf.chunks_exact_mut(CHUNK_SIZE).enumerate() { assert_eq!(chunk.len(), CHUNK_SIZE); for (k, v) in chunk.iter().enumerate() { @@ -31,17 +33,17 @@ fn correctness_random() { fn correctness_manual() { let mut ringbuf = RingBuf::new(8, 0_u32); - ringbuf.push_from_iter(1..4); + assert_eq!(ringbuf.push_from_iter(1..4), 3); let mut iter = ringbuf.chunks_exact_mut(4); assert_eq!(iter.next(), None); - ringbuf.push(4); + assert!(ringbuf.push(4)); let mut iter = ringbuf.chunks_exact_mut(4); assert_eq!(iter.next(), Some([1, 2, 3, 4].as_mut_slice())); assert_eq!(iter.next(), None); - ringbuf.push_from_iter(5..8); + assert_eq!(ringbuf.push_from_iter(5..8), 3); let mut iter = ringbuf.chunks_exact_mut(4); assert_eq!(iter.next(), None); - ringbuf.push_from_iter(8..14); + assert_eq!(ringbuf.push_from_iter_unchecked(8..14), 6); let mut iter = ringbuf.chunks_exact_mut(4); assert_eq!(iter.next(), Some([13, 6, 7, 8].as_mut_slice())); assert_eq!(iter.next(), Some([9, 10, 11, 12].as_mut_slice()));