read-write-buf/src/lib.rs

196 lines
4.6 KiB
Rust

#![no_std]
pub struct ReadWriteBuf<const N: usize> {
buffer: [u8; N],
read_cursor: usize,
write_cursor: usize,
full: bool,
}
impl<const N: usize> Default for ReadWriteBuf<N> {
fn default() -> Self {
Self::new()
}
}
impl<const N: usize> ReadWriteBuf<N> {
pub fn new() -> ReadWriteBuf<N> {
if N == 0 {
panic!("N cannot be zero");
}
ReadWriteBuf {
buffer: [0; N],
read_cursor: 0,
write_cursor: 0,
full: false,
}
}
pub fn is_empty(&self) -> bool {
self.read_cursor == self.write_cursor && !self.full
}
pub fn is_full(&self) -> bool {
self.full
}
pub fn for_reading(&mut self) -> Option<&mut [u8]> {
let (start, stop) = if self.read_cursor < self.write_cursor {
(self.read_cursor, self.write_cursor)
} else if !self.full {
(self.read_cursor, N)
} else {
return None;
};
Some(&mut self.buffer[start..stop])
}
pub fn for_writing(&self) -> Option<&[u8]> {
let (start, stop) = if self.write_cursor < self.read_cursor {
(self.write_cursor, self.read_cursor)
} else if self.full || self.read_cursor < self.write_cursor {
(self.write_cursor, N)
} else {
return None;
};
Some(&self.buffer[start..stop])
}
pub fn advance_read(&mut self, count: usize) {
self.read_cursor = (self.read_cursor + count) % N;
if self.read_cursor == self.write_cursor && count > 0 {
self.full = true;
}
}
pub fn advance_write(&mut self, count: usize) {
self.write_cursor = (self.write_cursor + count) % N;
if count > 0 {
self.full = false;
}
}
}
#[cfg(test)]
mod tests {
use super::ReadWriteBuf;
#[test]
fn read_exact_length_works() {
let mut buf = ReadWriteBuf::<10>::new();
assert!(buf.is_empty());
assert!(buf.for_writing().is_none());
let read_into = buf.for_reading().unwrap();
assert_eq!(read_into.len(), 10);
buf.advance_read(10);
assert!(buf.is_full());
assert_eq!(buf.read_cursor, buf.write_cursor);
let write_from = buf.for_writing().unwrap();
assert_eq!(write_from.len(), 10);
buf.advance_write(10);
assert!(!buf.full);
assert_eq!(buf.read_cursor, buf.write_cursor);
let read_from = buf.for_reading().unwrap();
assert_eq!(read_from.len(), 10);
assert!(buf.for_writing().is_none());
}
#[test]
fn from_0_0_reads_whole_len() {
let mut buf = ReadWriteBuf::<16>::new();
let slice = buf.for_reading().unwrap();
assert_eq!(slice.len(), 16);
}
#[test]
fn from_5_0_reads_11() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_read(5);
let slice = buf.for_reading().unwrap();
assert_eq!(slice.len(), 11);
}
#[test]
fn from_0_5_reads_5() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_write(5);
let slice = buf.for_reading().unwrap();
assert_eq!(slice.len(), 5);
}
#[test]
fn from_5_5_reads_11() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_read(5);
buf.advance_write(5);
let slice = buf.for_reading().unwrap();
assert_eq!(slice.len(), 11);
}
#[test]
fn from_5_5_full_reads_0() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_write(5);
buf.advance_read(5);
assert!(buf.for_reading().is_none());
}
#[test]
fn from_0_0_writes_0() {
let buf = ReadWriteBuf::<16>::new();
assert!(buf.for_writing().is_none());
}
#[test]
fn from_5_0_writes_5() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_read(5);
let slice = buf.for_writing().unwrap();
assert_eq!(slice.len(), 5);
}
#[test]
fn from_0_5_writes_11() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_write(5);
let slice = buf.for_writing().unwrap();
assert_eq!(slice.len(), 11);
}
#[test]
fn from_5_5_writes_0() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_read(5);
buf.advance_write(5);
assert!(buf.for_writing().is_none());
}
#[test]
fn from_5_5_full_writes_11() {
let mut buf = ReadWriteBuf::<16>::new();
buf.advance_write(5);
buf.advance_read(5);
let slice = buf.for_writing().unwrap();
assert_eq!(slice.len(), 11);
}
}