Skip to content

Instantly share code, notes, and snippets.

@ctcherry
Forked from timClicks/ringo.rs
Last active June 28, 2023 20:58
Show Gist options
  • Save ctcherry/04d17139f48b9448a754f6b51a7505a2 to your computer and use it in GitHub Desktop.
Save ctcherry/04d17139f48b9448a754f6b51a7505a2 to your computer and use it in GitHub Desktop.
Ring buffer implementation based on https://www.youtube.com/watch?v=TQVwv_e_rMw
#[derive(Debug)]
struct RingBuffer<T: Clone> {
storage: Vec<Option<T>>,
read_idx: usize,
write_idx: usize,
len: usize
}
#[derive(Debug, PartialEq)]
struct Full;
impl<T: Clone> RingBuffer<T> {
fn new(capacity: usize) -> Self {
RingBuffer {
storage: vec![None; capacity],
read_idx: 0,
write_idx: 0,
len: 0
}
}
fn push(&mut self, item: T) -> Result<(), Full> {
if self.is_full() {
return Err(Full);
}
self.storage[self.write_idx] = Some(item);
self.write_idx = self.next_idx(self.write_idx);
self.len += 1;
Ok(())
}
fn pull(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
let item = &self.storage[self.read_idx].take();
self.read_idx = self.next_idx(self.read_idx);
self.len -= 1;
item.clone()
}
fn next_idx(&self, idx: usize) -> usize {
(idx + 1) % self.storage.len()
}
fn is_empty(&self) -> bool {
self.len == 0
}
fn is_full(&self) -> bool {
self.len == self.storage.len()
}
}
fn main() {
println!("Hello, Internet! Let's learn about ring buffers!");
let mut b = RingBuffer::<i32>::new(3);
let r1 = b.pull();
assert!(r1.is_none());
let r2 = b.push(10);
assert_eq!(b.len, 1);
assert!(r2.is_ok());
let _ = b.push(9);
let _ = b.push(8);
assert!(!b.is_empty());
assert!(b.is_full());
assert_eq!(b.len, 3);
let rfull = b.push(7);
assert_eq!(rfull, Err(Full));
let r3 = b.pull();
assert_eq!(r3, Some(10));
assert!(!b.is_full());
let r4 = b.pull();
assert_eq!(r4, Some(9));
let r5 = b.pull();
assert_eq!(r5, Some(8));
assert!(b.is_empty());
let r6 = b.pull();
assert!(r6.is_none());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment