An arbitrarily large circle buffer
This commit is contained in:
commit
4eab0cc144
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal 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
159
src/lib.rs
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue