An arbitrarily large circle buffer

This commit is contained in:
Aode (lion) 2022-02-16 15:11:37 -05:00
commit 4eab0cc144
3 changed files with 169 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "read-write-buf"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

159
src/lib.rs Normal file
View file

@ -0,0 +1,159 @@
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 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 self.write_cursor != self.read_cursor {
self.full = false;
}
}
}
#[cfg(test)]
mod tests {
use super::ReadWriteBuf;
#[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);
}
}