kernel/collections/
ring.rs

1use core::mem::MaybeUninit;
2
3/// A fixed size ring buffer
4pub struct RingBuffer<T, const N: usize> {
5    buffer: [MaybeUninit<T>; N],
6    read_index: usize,
7    write_index: usize,
8}
9
10#[allow(dead_code)]
11impl<T, const N: usize> RingBuffer<T, N> {
12    pub fn try_push(&mut self, value: T) -> bool {
13        let next_index = (self.write_index + 1) % self.buffer.len();
14        if next_index == self.read_index {
15            return false;
16        }
17
18        self.buffer[self.write_index] = MaybeUninit::new(value);
19        self.write_index = next_index;
20
21        true
22    }
23
24    pub fn push(&mut self, value: T) {
25        let next_index = (self.write_index + 1) % self.buffer.len();
26        if next_index == self.read_index {
27            panic!("Ring buffer overflow");
28        }
29
30        self.buffer[self.write_index] = MaybeUninit::new(value);
31        self.write_index = next_index;
32    }
33
34    pub fn push_replace(&mut self, value: T) {
35        let next_index = (self.write_index + 1) % self.buffer.len();
36        // if the buffer is full, replace the oldest value
37        if next_index == self.read_index {
38            // drop the oldest value
39            unsafe { self.buffer[self.read_index].assume_init_drop() };
40            self.buffer[self.read_index] = MaybeUninit::new(value);
41            self.write_index = next_index;
42            // advance the read index
43            self.read_index = (self.read_index + 1) % self.buffer.len();
44        } else {
45            self.buffer[self.write_index] = MaybeUninit::new(value);
46            self.write_index = next_index;
47        }
48    }
49
50    pub fn pop(&mut self) -> Option<T> {
51        if self.read_index == self.write_index {
52            return None;
53        }
54
55        let value = unsafe { self.buffer[self.read_index].assume_init_read() };
56        self.read_index = (self.read_index + 1) % self.buffer.len();
57
58        Some(value)
59    }
60
61    pub fn clear(&mut self) {
62        self.read_index = 0;
63        self.write_index = 0;
64    }
65}
66
67#[allow(dead_code)]
68impl<T: Copy, const N: usize> RingBuffer<T, N> {
69    pub const fn empty() -> Self {
70        Self {
71            buffer: [MaybeUninit::<T>::uninit(); N],
72            read_index: 0,
73            write_index: 0,
74        }
75    }
76}