#![no_std]
extern crate alloc;
use core::num::NonZeroUsize;
use alloc::vec::Vec;
use slice_ring_buf::SliceRB;
pub struct ExpSliceRB<T: Default + Clone + Copy> {
buffer: SliceRB<T>,
index: isize,
data_len: usize,
}
impl<T: Default + Clone + Copy> ExpSliceRB<T> {
pub fn from_vec(vec: Vec<T>) -> Self {
Self {
buffer: SliceRB::from_vec(vec),
index: 0,
data_len: 0,
}
}
pub fn with_capacity(capacity: NonZeroUsize) -> Self {
let buffer = unsafe { SliceRB::new_uninit(capacity) };
Self {
buffer,
index: 0,
data_len: 0,
}
}
pub fn read_into(&mut self, mut slice: &mut [T]) -> usize {
if self.data_len == 0 {
return 0;
}
if self.data_len <= slice.len() {
let amount_to_copy = self.data_len;
slice = &mut slice[0..amount_to_copy];
self.buffer.read_into(slice, self.index);
self.index = self.buffer.constrain(self.index + amount_to_copy as isize);
self.data_len = 0;
return amount_to_copy;
}
self.buffer.read_into(slice, self.index);
self.index = self.buffer.constrain(self.index + slice.len() as isize);
self.data_len -= slice.len();
slice.len()
}
pub fn peek_into(&mut self, mut slice: &mut [T]) -> usize {
if self.data_len == 0 {
return 0;
}
if self.data_len <= slice.len() {
let amount_to_copy = self.data_len;
slice = &mut slice[0..amount_to_copy];
self.buffer.read_into(slice, self.index);
return amount_to_copy;
}
self.buffer.read_into(slice, self.index);
slice.len()
}
pub fn write(&mut self, slice: &[T]) {
let new_len = self.data_len + slice.len();
if new_len > self.buffer.len().get() {
self.reserve(new_len - self.buffer.len().get());
}
self.buffer
.write_latest(slice, self.index + self.data_len as isize);
self.data_len = new_len;
}
pub fn try_write(&mut self, slice: &[T]) -> Result<(), ()> {
let new_len = self.data_len + slice.len();
if new_len > self.buffer.len().get() {
return Err(());
}
self.buffer
.write_latest(slice, self.index + self.data_len as isize);
self.data_len = new_len;
Ok(())
}
pub fn reserve(&mut self, additional: usize) {
if additional == 0 {
return;
}
let data_end = self.index as usize + self.data_len;
let prev_buffer_len = self.buffer.len().get();
unsafe {
self.buffer
.set_len_uninit(NonZeroUsize::new(prev_buffer_len + additional).unwrap());
}
if data_end > prev_buffer_len {
let wrapped_data_len = data_end - prev_buffer_len;
let start_data_len = self.data_len - wrapped_data_len;
let (src, dst) = self.buffer.raw_data_mut().split_at_mut(self.index as usize);
if self.data_len > dst.len() {
let second_cpy_len = self.data_len - dst.len();
dst[start_data_len..start_data_len + additional]
.copy_from_slice(&src[0..additional]);
src.copy_within(additional..additional + second_cpy_len, 0);
} else {
dst[start_data_len..start_data_len + wrapped_data_len]
.copy_from_slice(&src[0..wrapped_data_len]);
}
}
}
pub fn clear(&mut self) {
self.index = 0;
self.data_len = 0;
}
pub fn clear_and_shrink_to_capacity(&mut self, capacity: NonZeroUsize) {
self.clear();
unsafe {
self.buffer.set_len_uninit(capacity);
}
self.buffer.shrink_to_fit();
}
pub fn capacity(&self) -> NonZeroUsize {
self.buffer.len()
}
pub fn raw_capacity(&self) -> NonZeroUsize {
self.buffer.capacity()
}
pub fn len(&self) -> usize {
self.data_len
}
pub fn data_left(&self) -> usize {
self.buffer.len().get() - self.data_len
}
pub fn is_empty(&self) -> bool {
self.data_len == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let mut buf: ExpSliceRB<u32> = ExpSliceRB::with_capacity(NonZeroUsize::new(4).unwrap());
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity().get(), 4);
let data = [0u32, 1, 2, 3];
buf.write(&data);
assert_eq!(buf.len(), 4);
assert_eq!(buf.buffer.raw_data(), data);
let mut read = [0u32; 4];
assert_eq!(buf.peek_into(&mut read), 4);
assert_eq!(read, data);
assert_eq!(buf.len(), 4);
assert_eq!(buf.capacity().get(), 4);
assert_eq!(buf.read_into(&mut read), 4);
assert_eq!(read, data);
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity().get(), 4);
let mut read_1 = [5u32; 2];
let mut read_2 = [5u32; 1];
let mut read_3 = [5u32; 2];
buf.write(&data);
assert_eq!(buf.read_into(&mut read_1), 2);
assert_eq!(read_1, [0u32, 1]);
assert_eq!(buf.read_into(&mut read_2), 1);
assert_eq!(read_2, [2u32]);
assert_eq!(buf.read_into(&mut read_3), 1);
assert_eq!(read_3, [3u32, 5]);
assert_eq!(buf.index, 0);
assert_eq!(buf.len(), 0);
buf.write(&data);
buf.read_into(&mut read_1);
buf.write(&read_3);
assert_eq!(buf.len(), 4);
assert_eq!(buf.capacity().get(), 4);
assert_eq!(buf.buffer.raw_data(), [3, 5, 2, 3]);
buf.read_into(&mut read);
assert_eq!(read, [2, 3, 3, 5]);
assert_eq!(buf.index, 2);
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity().get(), 4);
buf.write(&data);
assert_eq!(buf.buffer.raw_data(), [2, 3, 0, 1]);
buf.write(&read_3);
assert_eq!(buf.len(), 6);
assert_eq!(buf.capacity().get(), 6);
assert_eq!(buf.buffer.raw_data(), [3, 5, 0, 1, 2, 3]);
buf.write(&read_2);
assert_eq!(buf.len(), 7);
assert_eq!(buf.capacity().get(), 7);
assert_eq!(buf.buffer.raw_data(), [5, 2, 0, 1, 2, 3, 3]);
buf.write(&data);
assert_eq!(buf.len(), 11);
assert_eq!(buf.capacity().get(), 11);
assert_eq!(buf.buffer.raw_data(), [2, 3, 0, 1, 2, 3, 3, 5, 2, 0, 1]);
buf.read_into(&mut read_2);
assert_eq!(read_2, [0u32]);
buf.write(&data);
assert_eq!(buf.len(), 14);
assert_eq!(buf.capacity().get(), 14);
assert_eq!(
buf.buffer.raw_data(),
[1, 2, 3, 1, 2, 3, 3, 5, 2, 0, 1, 2, 3, 0]
);
buf.read_into(&mut read);
buf.read_into(&mut read);
buf.read_into(&mut read);
assert_eq!(read, [2, 3, 0, 1]);
assert_eq!(buf.read_into(&mut read), 2);
assert_eq!(read, [2, 3, 0, 1]);
buf.clear();
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity().get(), 14);
buf.clear_and_shrink_to_capacity(NonZeroUsize::new(5).unwrap());
assert_eq!(buf.capacity().get(), 5);
assert!(buf.raw_capacity().get() >= 5);
}
}