rs_matter/utils/storage/
ringbuf.rs1use core::cmp::min;
19
20use crate::utils::init::{init, Init};
21
22#[derive(Debug)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub struct RingBuf<const N: usize> {
26 buf: crate::utils::storage::Vec<u8, N>,
27 start: usize,
28 end: usize,
29 non_empty: bool,
30}
31
32impl<const N: usize> Default for RingBuf<N> {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl<const N: usize> RingBuf<N> {
39 #[inline(always)]
41 pub const fn new() -> Self {
42 Self {
43 buf: crate::utils::storage::Vec::new(),
44 start: 0,
45 end: 0,
46 non_empty: false,
47 }
48 }
49
50 pub fn init() -> impl Init<Self> {
52 init!(Self {
53 buf <- crate::utils::storage::Vec::init(),
54 start: 0,
55 end: 0,
56 non_empty: false,
57 })
58 }
59
60 #[inline(always)]
65 pub fn push(&mut self, data: &[u8]) -> usize {
66 unwrap!(self.buf.resize_default(N));
68
69 let mut offset = 0;
70
71 while offset < data.len() {
72 let len = min(self.buf.len() - self.end, data.len() - offset);
73
74 self.buf[self.end..self.end + len].copy_from_slice(&data[offset..offset + len]);
75
76 offset += len;
77
78 if self.non_empty && self.start >= self.end && self.start < self.end + len {
79 self.start = self.end + len;
81 }
82
83 self.end += len;
84
85 self.wrap();
86
87 self.non_empty = true;
88 }
89
90 self.len()
91 }
92
93 #[inline(always)]
98 pub fn push_byte(&mut self, data: u8) -> usize {
99 unwrap!(self.buf.resize_default(N));
101
102 self.buf[self.end] = data;
103
104 if self.non_empty && self.start == self.end {
105 self.start = self.end + 1;
107 }
108
109 self.end += 1;
110
111 self.wrap();
112
113 self.non_empty = true;
114
115 self.len()
116 }
117
118 #[inline(always)]
121 pub fn pop_byte(&mut self) -> Option<u8> {
122 let mut buf = [0; 1];
123
124 if self.pop(&mut buf) == 1 {
125 Some(buf[0])
126 } else {
127 None
128 }
129 }
130
131 #[inline(always)]
134 pub fn pop(&mut self, out_buf: &mut [u8]) -> usize {
135 let mut offset = 0;
136
137 while offset < out_buf.len() && self.non_empty {
138 let len = min(
139 if self.start < self.end {
140 self.end
141 } else {
142 self.buf.len()
143 } - self.start,
144 out_buf.len() - offset,
145 );
146
147 out_buf[offset..offset + len].copy_from_slice(&self.buf[self.start..self.start + len]);
148
149 self.start += len;
150
151 self.wrap();
152
153 if self.start == self.end {
154 self.non_empty = false
155 }
156
157 offset += len;
158 }
159
160 offset
161 }
162
163 #[inline(always)]
165 pub fn is_full(&self) -> bool {
166 self.start == self.end && self.non_empty
167 }
168
169 #[inline(always)]
171 pub fn is_empty(&self) -> bool {
172 !self.non_empty
173 }
174
175 #[inline(always)]
177 #[allow(unused)]
178 pub fn len(&self) -> usize {
179 if !self.non_empty {
180 0
181 } else if self.start < self.end {
182 self.end - self.start
183 } else {
184 self.buf.len() + self.end - self.start
185 }
186 }
187
188 #[inline(always)]
190 #[allow(unused)]
191 pub fn free(&self) -> usize {
192 N - self.len()
193 }
194
195 #[inline(always)]
197 pub fn clear(&mut self) {
198 self.start = 0;
199 self.end = 0;
200 self.non_empty = false;
201 }
202
203 #[inline(always)]
204 fn wrap(&mut self) {
205 if self.start == self.buf.len() {
206 self.start = 0;
207 }
208
209 if self.end == self.buf.len() {
210 self.end = 0;
211 }
212 }
213}
214
215impl<const N: usize> Iterator for RingBuf<N> {
216 type Item = u8;
217
218 fn next(&mut self) -> Option<Self::Item> {
219 self.pop_byte()
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[test]
228 fn push_pop() {
229 let mut rb = RingBuf::<4>::new();
230 assert!(rb.is_empty());
231
232 rb.push(&[0, 1, 2]);
233 assert_eq!(3, rb.len());
234 assert!(!rb.is_empty());
235 assert!(!rb.is_full());
236
237 rb.push(&[3]);
238 assert_eq!(4, rb.len());
239 assert!(!rb.is_empty());
240 assert!(rb.is_full());
241
242 let mut buf = [0; 256];
243
244 let len = rb.pop(&mut buf);
245 assert_eq!(4, len);
246 assert_eq!(&buf[0..4], &[0, 1, 2, 3]);
247 assert!(rb.is_empty());
248
249 rb.push(&[0, 1, 2, 3, 4, 5]);
250 assert_eq!(4, rb.len());
251 assert!(!rb.is_empty());
252 assert!(rb.is_full());
253
254 let len = rb.pop(&mut buf[..3]);
255 assert_eq!(3, len);
256 assert_eq!(&buf[0..len], &[2, 3, 4]);
257 assert!(!rb.is_empty());
258 assert!(!rb.is_full());
259
260 let len = rb.pop(&mut buf);
261 assert_eq!(1, len);
262 assert_eq!(&buf[0..len], &[5]);
263 assert!(rb.is_empty());
264 assert!(!rb.is_full());
265
266 let len = rb.pop(&mut buf);
267 assert_eq!(0, len);
268 assert!(rb.is_empty());
269 assert!(!rb.is_full());
270 }
271}