1#![allow(clippy::indexing_slicing)]
6#![allow(clippy::unwrap_used)]
7
8use crate::buf::Buffer;
9use core::ops::Index;
10use irox_bits::{Bits, BitsError, BitsErrorKind, Error, ErrorKind, MutBits};
11
12pub struct RoundU8Buffer<const N: usize> {
15 buf: [u8; N],
16 head: usize,
17 tail: usize,
18 size: usize,
19 mod_count: u32,
20}
21
22impl<const N: usize> RoundU8Buffer<N> {
23 pub fn pop_n_front<const L: usize>(&mut self) -> Option<[u8; L]> {
24 if self.size < L || N < L {
25 return None;
26 }
27 self.size -= L;
28 self.mod_count = self.mod_count.wrapping_add(1);
29 let mut out = [0u8; L];
30 for out in out.iter_mut().take(L) {
31 *out = self.buf[self.head];
32 if self.head != self.tail {
35 self.head += 1;
36 }
37 if self.head >= N {
39 self.head = 0;
40 }
41 }
42 Some(out)
43 }
44
45 pub const fn available_capacity(&self) -> usize {
48 N - self.size
49 }
50
51 pub fn as_ref_mut<F: FnMut(usize, &mut [u8]) -> Result<usize, BitsError>>(
54 &mut self,
55 mut func: F,
56 ) -> Result<(), BitsError> {
57 let used = func(self.size, &mut self.buf)?;
58 self.size = used;
59 Ok(())
60 }
61
62 pub fn as_ref_used(&self) -> (&[u8], &[u8]) {
63 let a_start = self.head;
64 let a_end = (a_start + self.size).min(N);
65 let a_used = a_end - a_start;
66 let b_start = 0;
67 let b_end = b_start + self.size - a_used;
68 let a = self.buf.get(a_start..a_end).unwrap_or_default();
69 let b = self.buf.get(b_start..b_end).unwrap_or_default();
70 (a, b)
71 }
72
73 pub fn as_ref_mut_available(&mut self) -> &mut [u8] {
74 if self.is_full() {
75 return &mut [];
76 } else if self.is_empty() {
77 self.clear();
78 return &mut self.buf;
79 }
80 if self.tail > self.head {
81 let a_start = (self.tail + 1).min(N);
83 let a_end = N;
84 let a_avail = a_end - a_start;
85 if a_avail > 0 {
86 return self.buf.get_mut(a_start..a_end).unwrap_or_default();
87 }
88 return self.buf.get_mut(0..self.head).unwrap_or_default();
89 }
90 self.buf.get_mut(self.tail..self.head).unwrap_or_default()
92 }
93
94 pub fn append_all(&mut self, vals: &[u8]) -> Result<(), BitsError> {
97 for v in vals {
98 if self.push_back(*v).is_err() {
99 return Err(BitsErrorKind::OutOfMemory.into());
100 };
101 }
102 Ok(())
103 }
104
105 pub fn append_some(&mut self, vals: &[u8]) -> usize {
109 let mut used = 0;
110 for v in vals {
111 if self.push_back(*v).is_err() {
112 return used;
113 }
114 used += 1;
115 }
116 used
117 }
118
119 pub fn consume(&mut self, amt: usize) {
122 if amt >= self.size {
123 return self.clear();
124 }
125 self.head += amt;
126 self.size -= amt;
127 if self.head >= N {
128 self.head -= N;
129 }
130 }
131
132 pub fn mark_some_used(&mut self, used: usize) -> Result<(), BitsError> {
136 if self.size + used > N {
137 return Err(BitsErrorKind::OutOfMemory.into());
138 }
139 self.size += used;
140 self.tail += used;
141 if self.tail >= N {
142 self.tail -= N;
143 }
144 Ok(())
145 }
146
147 pub fn limit(&mut self, limit: usize) -> Result<(), BitsError> {
151 if limit > N || self.size < limit {
152 return BitsErrorKind::InvalidInput.err("Invalid limit");
153 }
154 self.size = limit;
155 Ok(())
156 }
157}
158
159impl<const N: usize> From<[u8; N]> for RoundU8Buffer<N> {
160 fn from(value: [u8; N]) -> Self {
161 Self {
162 buf: value,
163 head: 0,
164 tail: N - 1,
165 size: N,
166 mod_count: 0,
167 }
168 }
169}
170
171pub struct RoundU8BufferIter<const N: usize> {
173 buf: RoundU8Buffer<N>,
174}
175
176impl<const N: usize> Iterator for RoundU8BufferIter<N> {
177 type Item = u8;
178
179 fn next(&mut self) -> Option<Self::Item> {
180 self.buf.pop_front()
181 }
182}
183
184impl<const N: usize> IntoIterator for RoundU8Buffer<N> {
185 type Item = u8;
186 type IntoIter = RoundU8BufferIter<N>;
187
188 fn into_iter(self) -> Self::IntoIter {
189 RoundU8BufferIter { buf: self }
190 }
191}
192
193impl<const N: usize> Default for RoundU8Buffer<N> {
194 fn default() -> Self {
195 RoundU8Buffer {
196 buf: [Default::default(); N],
197 head: 0,
198 tail: 0,
199 size: 0,
200 mod_count: 0,
201 }
202 }
203}
204
205impl<const N: usize> Buffer<u8> for RoundU8Buffer<N> {
206 fn get(&self, index: usize) -> Option<&u8> {
207 if index >= N || index >= self.size {
208 return None;
209 }
210 Some(&self.buf[index])
211 }
212
213 fn get_mut(&mut self, index: usize) -> Option<&mut u8> {
214 if index >= N || index >= self.size {
215 return None;
216 }
217 Some(&mut self.buf[index])
218 }
219
220 fn capacity(&self) -> usize {
221 N
222 }
223
224 fn len(&self) -> usize {
225 self.size
226 }
227
228 fn clear(&mut self) {
229 self.head = 0;
230 self.tail = 0;
231 self.size = 0;
232 self.mod_count = self.mod_count.wrapping_add(1);
233 self.buf.fill(0);
234 }
235
236 fn front(&self) -> Option<&u8> {
237 Some(&self.buf[self.head])
238 }
239
240 fn front_mut(&mut self) -> Option<&mut u8> {
241 Some(&mut self.buf[self.head])
242 }
243
244 fn back(&self) -> Option<&u8> {
245 Some(&self.buf[self.tail])
246 }
247
248 fn back_mut(&mut self) -> Option<&mut u8> {
249 Some(&mut self.buf[self.tail])
250 }
251
252 fn pop_front(&mut self) -> Option<u8> {
253 if self.size == 0 || N == 0 {
254 return None;
255 }
256 self.size -= 1;
257 self.mod_count = self.mod_count.wrapping_add(1);
258
259 let out = Some(self.buf[self.head]);
260 self.buf[self.head] = 0;
261 if self.size > 0 {
263 self.head += 1;
264 }
265 if self.head >= N {
267 self.head = 0;
268 }
269 out
270 }
271
272 fn pop_back(&mut self) -> Option<u8> {
273 if self.size == 0 || N == 0 {
274 return None;
276 }
277 let out = Some(self.buf[self.tail]);
278 self.buf[self.tail] = 0;
279 self.mod_count = self.mod_count.wrapping_add(1);
280
281 self.size -= 1;
282 if self.head != self.tail {
285 if self.tail == 0 {
287 self.tail = N - 1;
288 } else {
289 self.tail -= 1;
290 }
291 }
292 out
293 }
294
295 fn push_front(&mut self, value: u8) -> Result<(), u8> {
296 if self.size == N || N == 0 {
297 Err(value)
299 } else if self.size == 0 {
300 self.mod_count = self.mod_count.wrapping_add(1);
301
302 self.head = 0;
303 self.tail = 0;
304 self.buf[0] = value;
305 self.size = 1;
306 Ok(())
307 } else {
308 self.mod_count = self.mod_count.wrapping_add(1);
309
310 if self.head == 0 {
311 self.head = N - 1;
312 }
313 self.buf[self.head] = value;
314 self.size += 1;
315 Ok(())
316 }
317 }
318
319 fn push_back(&mut self, value: u8) -> Result<(), u8> {
320 if self.size == N || N == 0 {
321 Err(value)
323 } else if self.size == 0 {
324 self.mod_count = self.mod_count.wrapping_add(1);
325
326 self.head = 0;
328 self.tail = 0;
329 self.size = 1;
330 self.buf[0] = value;
331 Ok(())
332 } else {
333 self.mod_count = self.mod_count.wrapping_add(1);
334
335 self.size += 1;
337 self.tail += 1;
338 if self.tail == N {
339 self.tail = 0;
340 }
341 self.buf[self.tail] = value;
342 Ok(())
343 }
344 }
345}
346
347impl<const N: usize> Bits for RoundU8Buffer<N> {
348 fn next_u8(&mut self) -> Result<Option<u8>, Error> {
349 Ok(self.pop_front())
350 }
351
352 fn read_be_u32(&mut self) -> Result<u32, Error> {
353 let a = self
354 .pop_n_front::<4>()
355 .ok_or_else(|| BitsError::new(BitsErrorKind::UnexpectedEof, "EOF"))?;
356 Ok(u32::from_be_bytes(a))
357 }
358}
359impl<const N: usize> Bits for &mut RoundU8Buffer<N> {
360 fn next_u8(&mut self) -> Result<Option<u8>, Error> {
361 Ok(self.pop_front())
362 }
363
364 fn read_be_u32(&mut self) -> Result<u32, Error> {
365 let a = self
366 .pop_n_front::<4>()
367 .ok_or_else(|| BitsError::new(BitsErrorKind::UnexpectedEof, "EOF"))?;
368 Ok(u32::from_be_bytes(a))
369 }
370}
371
372impl<const N: usize> MutBits for RoundU8Buffer<N> {
373 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
374 self.push_back(val)
375 .map_err(|_| ErrorKind::OutOfMemory.into())
376 }
377}
378
379impl<const N: usize> MutBits for &mut RoundU8Buffer<N> {
380 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
381 self.push_back(val)
382 .map_err(|_| ErrorKind::OutOfMemory.into())
383 }
384}
385
386#[allow(clippy::panic)]
387impl<const N: usize> Index<usize> for RoundU8Buffer<N> {
388 type Output = u8;
389
390 fn index(&self, index: usize) -> &Self::Output {
391 assert!(index < self.size, "{index} >= {}", self.size);
392 let mut offset = self.head + index;
393 if offset >= N {
394 offset -= N;
395 }
396 let Some(val) = self.buf.get(offset) else {
397 panic!("expected value at offset {offset} but was empty!");
398 };
399 val
400 }
401}
402
403#[cfg(test)]
404mod tests {
405 use crate::buf::Buffer;
406 use irox_bits::Error;
407
408 macro_rules! assert_empty {
409 ($buf:ident) => {
410 assert_eq!(0, $buf.len());
411 assert_eq!(None, $buf.pop_front());
412 assert_eq!(None, $buf.pop_back());
413 };
414 }
415
416 macro_rules! assert_full {
417 ($buf:ident, $sz:literal, $elem:expr) => {
418 assert_eq!($sz, $buf.len());
419 assert_eq!(Err($elem), $buf.push_back($elem));
420 assert_eq!($sz, $buf.len());
421 assert_eq!(Err($elem), $buf.push_front($elem));
422 assert_eq!($sz, $buf.len());
423 };
424 }
425
426 #[test]
427 pub fn test_push_some() -> Result<(), u32> {
428 let mut buf = crate::buf::RoundU8Buffer::<3>::default();
429 assert_empty!(buf);
430
431 buf.push_back(10)?;
432 assert_eq!(1, buf.len());
433 assert_eq!(0, buf.head);
434 assert_eq!(0, buf.tail);
435
436 buf.push_back(15)?;
437 assert_eq!(2, buf.len());
438 assert_eq!(0, buf.head);
439 assert_eq!(1, buf.tail);
440
441 buf.push_back(20)?;
442 assert_eq!(3, buf.len());
443 assert_eq!(0, buf.head);
444 assert_eq!(2, buf.tail);
445
446 assert_full!(buf, 3, 25);
447
448 assert_eq!(Some(10), buf.pop_front());
449 assert_eq!(2, buf.len());
450 assert_eq!(1, buf.head);
451 assert_eq!(2, buf.tail);
452
453 buf.push_back(30)?;
454 assert_eq!(3, buf.len());
455 assert_eq!(1, buf.head);
456 assert_eq!(0, buf.tail);
457
458 assert_full!(buf, 3, 35);
459
460 assert_eq!(Some(15), buf.pop_front());
461 assert_eq!(2, buf.len());
462 assert_eq!(2, buf.head);
463 assert_eq!(0, buf.tail);
464
465 assert_eq!(Some(20), buf.pop_front());
466 assert_eq!(1, buf.len());
467 assert_eq!(0, buf.head);
468 assert_eq!(0, buf.tail);
469
470 assert_eq!(Some(30), buf.pop_front());
471 assert_eq!(0, buf.len());
472 assert_eq!(0, buf.head);
473 assert_eq!(0, buf.tail);
474
475 assert_empty!(buf);
476 assert_empty!(buf);
477
478 Ok(())
479 }
480
481 #[test]
482 pub fn test_slicing() -> Result<(), Error> {
483 let mut buf = crate::buf::RoundU8Buffer::<10>::default();
484 assert_eq!(0, buf.len());
485 let (a, b) = buf.as_ref_used();
486 assert_eq!(0, a.len());
487 assert_eq!(0, b.len());
488 let avail = buf.as_ref_mut_available();
489 assert_eq!(10, avail.len());
490
491 for i in 0..5 {
492 buf.push_back(i).unwrap();
493 }
494 assert_eq!(5, buf.len());
495
496 let (a, b) = buf.as_ref_used();
497 assert_eq!(5, a.len());
498 assert_eq!(0, b.len());
499 assert_eq!(&[0, 1, 2, 3, 4], a);
500 let avail = buf.as_ref_mut_available();
501 assert_eq!(5, avail.len());
502 assert_eq!(&[0, 0, 0, 0, 0], avail);
503
504 assert_eq!(Some(0), buf.pop_front());
505 assert_eq!(4, buf.len());
506 let (a, b) = buf.as_ref_used();
507 assert_eq!(4, a.len());
508 assert_eq!(0, b.len());
509 assert_eq!(&[1, 2, 3, 4], a);
510 let avail = buf.as_ref_mut_available();
511 assert_eq!(5, avail.len());
512 assert_eq!(&[0, 0, 0, 0, 0], avail);
513
514 buf.append_all(&[5, 6, 7, 8, 9, 10])?;
515 assert_eq!(10, buf.len());
516 let (a, b) = buf.as_ref_used();
517 assert_eq!(9, a.len());
518 assert_eq!(1, b.len());
519 assert_eq!(&[1, 2, 3, 4, 5, 6, 7, 8, 9], a);
520 assert_eq!(&[10], b);
521 let avail = buf.as_ref_mut_available();
522 assert_eq!(0, avail.len());
523
524 assert_eq!(Some(10), buf.pop_back());
525 let avail = buf.as_ref_mut_available();
526 assert_eq!(1, avail.len());
527 assert_eq!(&[0], avail);
528
529 buf.consume(5);
530 assert_eq!(4, buf.len());
531 let (a, b) = buf.as_ref_used();
532 assert_eq!(&[6, 7, 8, 9], a);
533 assert_eq!(0, b.len());
534 buf.consume(4);
535 assert_eq!(0, buf.len());
536
537 let (a, b) = buf.as_ref_used();
538 assert_eq!(0, a.len());
539 assert_eq!(0, b.len());
540 let avail = buf.as_ref_mut_available();
541 assert_eq!(10, avail.len());
542 Ok(())
543 }
544}