chunkable-ringbuf/src/lib.rs

72 lines
1.7 KiB
Rust

#[cfg(test)]
mod test;
pub struct RingBuf<T> {
data: Vec<T>,
read_index: usize,
write_index: usize,
available: usize,
}
impl<T> RingBuf<T> {
pub fn new(size: usize, value: T) -> Self
where
T: Clone,
{
Self {
data: vec![value; size],
read_index: 0,
write_index: 0,
available: 0,
}
}
pub fn push(&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<I: Iterator<Item = T>>(&mut self, iter: I) {
let mut len = 0;
for value in iter {
self.data[self.write_index] = value;
self.write_index = (self.write_index + 1) % self.data.len();
len += 1;
}
self.available = (self.available + len).min(self.data.len());
}
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<T> {
assert_eq!(self.read_index % chunk_size, 0);
assert_eq!(self.data.len() % chunk_size, 0);
ChunksExactMut {
ringbuf: self,
chunk_size,
}
}
}
pub struct ChunksExactMut<'a, T> {
ringbuf: &'a mut RingBuf<T>,
chunk_size: usize,
}
impl<'a, T> Iterator for ChunksExactMut<'a, T> {
type Item = &'a mut [T];
fn next(&mut self) -> Option<Self::Item> {
if self.ringbuf.available >= self.chunk_size {
let read_index = self.ringbuf.read_index;
self.ringbuf.read_index =
(self.ringbuf.read_index + self.chunk_size) % self.ringbuf.data.len();
self.ringbuf.available -= self.chunk_size;
let ret: &mut [T] = &mut self.ringbuf.data[read_index..read_index + self.chunk_size];
let ret: &'a mut [T] = unsafe { std::mem::transmute(ret) };
Some(ret)
} else {
None
}
}
}