embassy_sync/
ring_buffer.rs

1use core::ops::Range;
2
3pub struct RingBuffer<const N: usize> {
4    start: usize,
5    end: usize,
6    full: bool,
7}
8
9impl<const N: usize> RingBuffer<N> {
10    pub const fn new() -> Self {
11        Self {
12            start: 0,
13            end: 0,
14            full: false,
15        }
16    }
17
18    pub fn push_buf(&mut self) -> Range<usize> {
19        if self.is_full() {
20            trace!("  ringbuf: push_buf full");
21            return 0..0;
22        }
23
24        let n = if self.start <= self.end {
25            N - self.end
26        } else {
27            self.start - self.end
28        };
29
30        trace!("  ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
31        self.end..self.end + n
32    }
33
34    pub fn push(&mut self, n: usize) {
35        trace!("  ringbuf: push {:?}", n);
36        if n == 0 {
37            return;
38        }
39
40        self.end = self.wrap(self.end + n);
41        self.full = self.start == self.end;
42    }
43
44    pub fn pop_buf(&mut self) -> Range<usize> {
45        if self.is_empty() {
46            trace!("  ringbuf: pop_buf empty");
47            return 0..0;
48        }
49
50        let n = if self.end <= self.start {
51            N - self.start
52        } else {
53            self.end - self.start
54        };
55
56        trace!("  ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
57        self.start..self.start + n
58    }
59
60    pub fn pop(&mut self, n: usize) {
61        trace!("  ringbuf: pop {:?}", n);
62        if n == 0 {
63            return;
64        }
65
66        self.start = self.wrap(self.start + n);
67        self.full = false;
68    }
69
70    pub fn is_full(&self) -> bool {
71        self.full
72    }
73
74    pub fn is_empty(&self) -> bool {
75        self.start == self.end && !self.full
76    }
77
78    #[allow(unused)]
79    pub fn len(&self) -> usize {
80        if self.is_empty() {
81            0
82        } else if self.start < self.end {
83            self.end - self.start
84        } else {
85            N + self.end - self.start
86        }
87    }
88
89    pub fn clear(&mut self) {
90        self.start = 0;
91        self.end = 0;
92        self.full = false;
93    }
94
95    fn wrap(&self, n: usize) -> usize {
96        assert!(n <= N);
97        if n == N {
98            0
99        } else {
100            n
101        }
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn push_pop() {
111        let mut rb: RingBuffer<4> = RingBuffer::new();
112        let buf = rb.push_buf();
113        assert_eq!(0..4, buf);
114        rb.push(4);
115
116        let buf = rb.pop_buf();
117        assert_eq!(0..4, buf);
118        rb.pop(1);
119
120        let buf = rb.pop_buf();
121        assert_eq!(1..4, buf);
122        rb.pop(1);
123
124        let buf = rb.pop_buf();
125        assert_eq!(2..4, buf);
126        rb.pop(1);
127
128        let buf = rb.pop_buf();
129        assert_eq!(3..4, buf);
130        rb.pop(1);
131
132        let buf = rb.pop_buf();
133        assert_eq!(0..0, buf);
134
135        let buf = rb.push_buf();
136        assert_eq!(0..4, buf);
137    }
138}