aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-13 20:03:11 -0400
committerBrian Cully <bjc@kublai.com>2019-08-13 20:11:57 -0400
commit8647cf58a27e56c9fd978c7340ee74c95fbec01f (patch)
tree0c0c3fdbd795be7996fa9fd72e5d31df65498d8f /src/lib.rs
parent680a95006deeb98e7c79fa30e3a264cfd6278fe9 (diff)
downloadstarb-8647cf58a27e56c9fd978c7340ee74c95fbec01f.tar.gz
starb-8647cf58a27e56c9fd978c7340ee74c95fbec01f.zip
Add Writer::unshift_from for batch copying data in.
This is just the inverse of Reader::shift and exists for the same reasons.
Diffstat (limited to 'src/lib.rs')
-rwxr-xr-xsrc/lib.rs52
1 files changed, 52 insertions, 0 deletions
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<T> = 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::<usize>::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::<usize>::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());
+ }
}