1#![cfg_attr(not(test), no_std)]
2
3pub struct BytearrayRingbuffer<const N: usize> {
4 buffer: [u8; N],
5 head: usize,
7 tail: usize,
9 empty: bool,
11}
12
13#[derive(Copy, Clone, Debug)]
14pub struct NotEnoughSpaceError;
15
16impl<const N: usize> BytearrayRingbuffer<N> {
17 pub const fn new() -> Self {
18 assert!(N > 8);
19 assert!(N < (u32::MAX as usize));
20 Self {
21 buffer: [0; N],
22 head: 0,
23 tail: 0,
24 empty: true,
25 }
26 }
27
28 pub const fn free(&self) -> usize {
30 self.bytes_unused().saturating_sub(8)
31 }
32
33 pub fn push(&mut self, data: &[u8]) -> Result<(), NotEnoughSpaceError> {
35 self._push(data, false)
36 }
37
38 pub fn push_force(&mut self, data: &[u8]) -> Result<(), NotEnoughSpaceError> {
40 self._push(data, true)
41 }
42
43 const fn bytes_unused(&self) -> usize {
45 if self.empty {
46 N
47 } else if self.head > self.tail {
48 N + self.tail - self.head
49 } else {
50 self.tail - self.head
51 }
52 }
53
54 fn _push(&mut self, data: &[u8], force: bool) -> Result<(), NotEnoughSpaceError> {
55 assert!(data.len() <= u32::MAX as usize);
56
57 if data.len() > N - 8 {
59 return Err(NotEnoughSpaceError);
60 }
61
62 if (data.len() + 8) > self.bytes_unused() {
64 if !force {
65 return Err(NotEnoughSpaceError);
66 }
67 while (data.len() + 8) > self.bytes_unused() {
68 self.pop_front();
69 }
70 }
71
72 let addr_a = self.head;
74 let addr_b = add_wrapping::<N>(self.head, 4);
75 let addr_c = add_wrapping::<N>(self.head, 4 + data.len());
76 let len_buffer: [u8; 4] = (data.len() as u32).to_ne_bytes();
77 write_wrapping(&mut self.buffer, addr_a, &len_buffer);
78 write_wrapping(&mut self.buffer, addr_b, data);
79 write_wrapping(&mut self.buffer, addr_c, &len_buffer);
80
81 self.head = add_wrapping::<N>(self.head, 8 + data.len());
82 self.empty = false;
83
84 Ok(())
85 }
86
87 pub fn pop_front(&mut self) -> Option<(&[u8], &[u8])> {
88 if self.empty {
89 return None;
90 }
91 let mut len_buffer = [0; 4];
92 read_wrapping(&self.buffer, self.tail, &mut len_buffer);
93 let len = u32::from_ne_bytes(len_buffer) as usize;
94
95 let index_data = add_wrapping::<N>(self.tail, 4);
96 let len_a = (N - index_data).min(len);
97 let a = &self.buffer[index_data..index_data + len_a];
98 let b = if len_a == len {
99 &[]
100 } else {
101 &self.buffer[..len - len_a]
102 };
103
104 self.tail = add_wrapping::<N>(self.tail, len + 8);
105 self.empty = self.head == self.tail;
106 Some((a, b))
107 }
108
109 pub fn iter_backwards<'a>(&'a self) -> IterBackwards<'a, N> {
110 IterBackwards {
111 buffer: &self.buffer,
112 head: self.head,
113 tail: self.tail,
114 empty: self.empty,
115 }
116 }
117
118 pub fn iter<'a>(&'a self) -> Iter<'a, N> {
119 Iter {
120 buffer: &self.buffer,
121 head: self.head,
122 tail: self.tail,
123 empty: self.empty,
124 }
125 }
126
127 pub fn count(&self) -> usize {
129 self.iter_backwards().count()
130 }
131
132 pub fn nth(&self, n: usize) -> Option<(&[u8], &[u8])> {
133 self.iter_backwards().nth(n)
134 }
135}
136
137pub struct IterBackwards<'a, const N: usize> {
138 buffer: &'a [u8; N],
139 head: usize,
140 tail: usize,
141 empty: bool,
142}
143
144impl<'a, const N: usize> Iterator for IterBackwards<'a, N> {
145 type Item = (&'a [u8], &'a [u8]);
146
147 fn next(&mut self) -> Option<Self::Item> {
148 if self.empty {
149 return None;
150 }
151
152 let index_len = sub_wrapping::<N>(self.head, 4);
154 let mut buf = [0u8; 4];
155 read_wrapping(self.buffer, index_len, &mut buf);
156 let len_data = u32::from_ne_bytes(buf) as usize;
157 debug_assert!((len_data + 8) <= N);
158
159 #[cfg(test)]
160 {
161 let index_len = sub_wrapping::<N>(self.head, 8 + len_data);
162 let mut buf = [0u8; 4];
163 read_wrapping(self.buffer, index_len, &mut buf);
164 let len_2 = u32::from_ne_bytes(buf) as usize;
165 assert_eq!(len_data, len_2);
166 }
167
168 let index_data = sub_wrapping::<N>(self.head, 4 + len_data);
170 let first = (N - index_data).min(len_data);
171 let slice_a = &self.buffer[index_data..index_data + first];
172 let slice_b = if first < len_data {
173 &self.buffer[..len_data - first]
174 } else {
175 &[]
176 };
177
178 self.head = sub_wrapping::<N>(self.head, 8 + len_data);
179 self.empty = self.head == self.tail;
180
181 Some((slice_a, slice_b))
182 }
183}
184
185impl<const N: usize> Default for BytearrayRingbuffer<N> {
186 fn default() -> Self {
187 Self::new()
188 }
189}
190
191pub struct Iter<'a, const N: usize> {
192 buffer: &'a [u8; N],
193 head: usize,
194 tail: usize,
195 empty: bool,
196}
197
198impl<'a, const N: usize> Iterator for Iter<'a, N> {
199 type Item = (&'a [u8], &'a [u8]);
200
201 fn next(&mut self) -> Option<Self::Item> {
202 if self.empty {
203 return None;
204 }
205
206 let bytes_used = if self.head > self.tail {
208 N + self.tail - self.head
209 } else {
210 self.tail - self.head
211 };
212 let bytes_valid = N - bytes_used;
213 debug_assert!(bytes_valid >= 8);
214
215 let mut buf = [0u8; 4];
217 read_wrapping(self.buffer, self.tail, &mut buf);
218 let len_data = u32::from_ne_bytes(buf) as usize;
219 debug_assert!((len_data + 8) <= N);
220 debug_assert!((len_data + 8) <= bytes_valid);
221
222 let index_data = add_wrapping::<N>(self.tail, 4);
224 let first = (N - index_data).min(len_data);
225 let slice_a = &self.buffer[index_data..index_data + first];
226 let slice_b = if first < len_data {
227 &self.buffer[..len_data - first]
228 } else {
229 &[]
230 };
231
232 self.tail = add_wrapping::<N>(self.tail, 8 + len_data);
233 self.empty = self.head == self.tail;
234
235 Some((slice_a, slice_b))
236 }
237}
238
239fn add_wrapping<const N: usize>(addr: usize, offset: usize) -> usize {
240 debug_assert!(addr < N);
241 debug_assert!(offset <= N);
242 let s = addr + offset;
243 if s < N { s } else { s - N }
244}
245
246fn sub_wrapping<const N: usize>(addr: usize, offset: usize) -> usize {
247 debug_assert!(addr < N);
248 debug_assert!(offset <= N);
249 if addr >= offset {
250 addr - offset
251 } else {
252 N + addr - offset
253 }
254}
255
256fn write_wrapping(buffer: &mut [u8], index: usize, data: &[u8]) {
258 let first = (buffer.len() - index).min(data.len());
259 buffer[index..index + first].copy_from_slice(&data[..first]);
260 if first < data.len() {
261 buffer[..data.len() - first].copy_from_slice(&data[first..]);
262 }
263}
264
265fn read_wrapping(buffer: &[u8], index: usize, data: &mut [u8]) {
266 let first = (buffer.len() - index).min(data.len());
267 data[..first].copy_from_slice(&buffer[index..index + first]);
268 if first < data.len() {
269 let remaining = data.len() - first;
270 data[first..].copy_from_slice(&buffer[..remaining]);
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use std::collections::VecDeque;
277
278 use super::BytearrayRingbuffer;
279
280 #[test]
281 fn push_some_packets() {
282 const N: usize = 64;
283 for start_offset in 0..N {
284 let mut buf = BytearrayRingbuffer::<N>::new();
285 buf.head = start_offset;
286 buf.tail = start_offset;
287
288 let free = 64 - 8;
289 assert_eq!(buf.free(), free);
290
291 buf.push(b"01234567").unwrap();
292 let free = free - 8 - 8;
293 assert_eq!(buf.free(), free);
294
295 buf.push(b"").unwrap();
296 let free = free - 8;
297 assert_eq!(buf.free(), free);
298
299 buf.push(b"0123").unwrap();
300 let free = free - 4 - 8;
301 assert_eq!(buf.free(), free);
302
303 buf.push(b"0123").unwrap();
304 let free = free - 4 - 8;
305 assert_eq!(buf.free(), free);
306 }
307 }
308
309 #[test]
310 fn push_force() {
311 let mut buf = BytearrayRingbuffer::<16>::new();
312 assert_eq!(buf.bytes_unused(), 16);
313
314 let a = b"012345";
315 let b = b"0123";
316
317 buf.push(a).unwrap();
318 assert_eq!(buf.bytes_unused(), 16 - a.len() - 8);
319
320 buf.push(b).unwrap_err();
321 assert_eq!(buf.bytes_unused(), 16 - a.len() - 8);
322
323 buf.push_force(b).unwrap();
324 assert_eq!(buf.bytes_unused(), 16 - b.len() - 8);
325 }
326
327 #[test]
328 fn push_all_data_lengths() {
329 for n in 0..(32 - 8) {
330 let mut buf = BytearrayRingbuffer::<32>::new();
331 let data = (0..n as u8).collect::<Vec<u8>>();
333
334 assert_eq!(buf.free(), 32 - 8);
335 buf.push(&data).unwrap();
336 assert_eq!(buf.free(), (32usize - 16).saturating_sub(n));
337 }
338 }
339
340 #[test]
341 fn push_sum_of_lengths_possible() {
342 let mut buf = BytearrayRingbuffer::<32>::new();
343 assert_eq!(buf.free(), 32 - 8);
345 buf.push(b"01234567").unwrap();
346 assert_eq!(buf.free(), 32 - 8 - 16);
347 buf.push(b"01234567").unwrap();
348 assert_eq!(buf.free(), 0);
349 }
350
351 #[test]
352 fn push_pop() {
353 const N: usize = 64;
354 for start_offset in 0..N {
355 eprintln!("--------------");
356 let mut buf = BytearrayRingbuffer::<N>::new();
357 buf.head = start_offset;
358 buf.tail = start_offset;
359
360 let data = b"01234567";
361 buf.push(data).unwrap();
362
363 let (a, b) = buf.pop_front().unwrap();
364 let mut out = Vec::new();
365 out.extend_from_slice(a);
366 out.extend_from_slice(b);
367
368 dbg!(out.as_slice());
369 assert!(data == out.as_slice());
370
371 assert_eq!(buf.head, buf.tail);
372 assert_eq!(buf.bytes_unused(), N);
373 }
374 }
375
376 #[test]
377 fn push_read_back() {
378 let data = [b"hello world" as &[u8], b"", b"test"];
379
380 const N: usize = 64;
381 for start_offset in 0..N {
382 let mut buf = BytearrayRingbuffer::<N>::new();
383 buf.head = start_offset;
384 buf.tail = start_offset;
385
386 for &d in &data {
387 buf.push(d).unwrap();
388 }
389
390 let mut it = buf.iter();
392 for &d in data.iter() {
393 let (a, b) = it.next().unwrap();
394 let mut ab = Vec::new();
395 ab.extend_from_slice(a);
396 ab.extend_from_slice(b);
397 let ab = ab.as_slice();
398 assert_eq!(d, ab);
399 }
400 assert_eq!(it.next(), None);
401
402 let mut it = buf.iter_backwards();
404 for &d in data.iter().rev() {
405 let (a, b) = it.next().unwrap();
406 let mut ab = Vec::new();
407 ab.extend_from_slice(a);
408 ab.extend_from_slice(b);
409 let ab = ab.as_slice();
410 assert_eq!(d, ab);
411 }
412 assert_eq!(it.next(), None);
413 }
414 }
415
416 #[test]
417 fn push_count() {
418 let mut buf = BytearrayRingbuffer::<64>::new();
419 buf.push(b"1234").unwrap();
420 assert_eq!(buf.count(), 1);
421 buf.push(b"1234").unwrap();
422 assert_eq!(buf.count(), 2);
423 buf.push(b"1234").unwrap();
424 assert_eq!(buf.count(), 3);
425 }
426
427 fn test_with_readback<const N: usize>(words: &[&'static str]) {
428 eprintln!("--------------------------");
429 let mut buf = BytearrayRingbuffer::<N>::new();
430 let mut current_words = VecDeque::new();
431 for &word in words {
432 eprintln!("adding {word:?}");
433 let word = word.to_owned();
434 let current_bytes: usize = current_words.iter().map(|w: &String| w.len() + 8).sum();
435 if current_bytes + 8 + word.len() > N {
436 current_words.pop_front();
437 }
438
439 buf.push_force(word.as_bytes()).unwrap();
440 current_words.push_back(word);
441
442 for (a, b) in buf.iter_backwards().zip(current_words.iter().rev()) {
443 eprintln!("read back {b:?}");
444 let mut st = String::new();
445 st.push_str(core::str::from_utf8(a.0).unwrap());
446 st.push_str(core::str::from_utf8(a.1).unwrap());
447 assert_eq!(st, *b);
448 }
449 }
450 }
451
452 #[test]
453 fn readback_various() {
454 test_with_readback::<32>(&["ab", "123", "hello", "world"]);
455 test_with_readback::<32>(&["", "", "a", "", "", ""]);
456 test_with_readback::<32>(&["", "", "ab", "", "", ""]);
457 test_with_readback::<32>(&["", "", "abc", "", "", ""]);
458 test_with_readback::<32>(&["", "", "abcd", "", "", ""]);
459 test_with_readback::<32>(&["", "", "abcde", "", "", ""]);
460
461 test_with_readback::<24>(&["0", "1", "a", "2", "3", "4"]);
462 test_with_readback::<24>(&["0", "1", "ab", "2", "3", "4"]);
463 test_with_readback::<24>(&["0", "1", "abc", "2", "3", "4"]);
464 test_with_readback::<24>(&["0", "1", "abcd", "2", "3", "4"]);
465 test_with_readback::<24>(&["0", "1", "abcde", "2", "3", "4"]);
466 test_with_readback::<24>(&["0", "1", "abcdef", "2", "3", "4"]);
467 test_with_readback::<24>(&["0", "1", "abcdefg", "2", "3", "4"]);
468 }
469}