From 8647cf58a27e56c9fd978c7340ee74c95fbec01f Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Tue, 13 Aug 2019 20:03:11 -0400 Subject: Add Writer::unshift_from for batch copying data in. This is just the inverse of Reader::shift and exists for the same reasons. --- src/lib.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 2089cfd..61d667b 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,6 +208,31 @@ where Ok(()) } } + + /// Copy as much of `buf` into the ring buffer. + /// + /// Returns the number of items copied. + pub fn unshift_from(&mut self, buf: &[T]) -> usize { + let rb: &mut RingBuffer = unsafe { mem::transmute(self.rb) }; + + let h = rb.head.load(Ordering::SeqCst); + let mut t = rb.tail.load(Ordering::SeqCst); + + let mylen = (t + CAPACITY - h) % CAPACITY; + let buflen = buf.len(); + let len = cmp::min(CAPACITY - mylen - 1, buflen); + + unsafe { + let rbuf = &mut *rb.buf.get(); + for i in 0..len { + *rbuf.get_unchecked_mut(t) = *buf.get_unchecked(i); + t = (t + 1) % CAPACITY; + } + } + + rb.tail.store(t, Ordering::SeqCst); + len + } } #[cfg(test)] @@ -329,4 +354,31 @@ mod test { assert!(rbr.shift().is_none()); } + + #[test] + fn unshift_from_smaller() { + let rb = RingBuffer::::new(0); + let (mut rbr, mut rbw) = rb.split(); + + let buf: [usize; CAPACITY / 2] = [0xdead; CAPACITY / 2]; + assert_eq!(rbw.unshift_from(&buf), CAPACITY / 2); + for i in 0..CAPACITY / 2 { + assert_eq!(rbr.shift(), Some(0xdead), "wrong value at index {}", i); + } + assert!(rbr.shift().is_none()); + } + + #[test] + fn unshift_from_bigger() { + let rb = RingBuffer::::new(0); + let (mut rbr, mut rbw) = rb.split(); + + let buf: [usize; CAPACITY * 2] = [0xdead; CAPACITY * 2]; + assert_eq!(rbw.unshift_from(&buf), CAPACITY - 1); + assert_eq!(rbw.unshift(0xbeef), Err(Error::BufferFull)); + for i in 0..CAPACITY - 1 { + assert_eq!(rbr.shift(), Some(0xdead), "wrong value at index {}", i); + } + assert!(rbr.shift().is_none()); + } } -- cgit v1.2.3