72 lines
1.7 KiB
Rust
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
|
|
}
|
|
}
|
|
}
|