1#![allow(clippy::indexing_slicing)]
6#![allow(clippy::unwrap_used)]
7use crate::buf::Buffer;
8use crate::iterators::LendingIterator;
9use crate::options::MaybeMap;
10use core::iter::zip;
11use core::ops::{Index, IndexMut};
12use irox_bits::{BitsError, BitsErrorKind, Error, MutBits, WriteToBEBits};
13#[derive(Clone)]
18pub struct FixedBuf<const N: usize, T: Sized> {
19 buf: [Option<T>; N],
20 len: usize,
21}
22impl<const N: usize, T: Sized> FixedBuf<N, T> {
23 const NONE_T: Option<T> = None;
24
25 pub const fn new() -> Self {
26 Self {
27 buf: [Self::NONE_T; N],
28 len: 0,
29 }
30 }
31}
32impl<const N: usize, T: Sized> Default for FixedBuf<N, T> {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl<const N: usize> core::fmt::Write for FixedBuf<N, u8> {
39 fn write_str(&mut self, s: &str) -> core::fmt::Result {
40 for b in s.as_bytes() {
41 self.push(*b).map_err(|_| core::fmt::Error)?;
42 }
43 Ok(())
44 }
45}
46impl<const N: usize> core::fmt::Write for FixedBuf<N, char> {
47 fn write_str(&mut self, s: &str) -> core::fmt::Result {
48 for b in s.chars() {
49 self.push(b).map_err(|_| core::fmt::Error)?;
50 }
51 Ok(())
52 }
53}
54
55impl<const N: usize, T: Sized> Buffer<T> for FixedBuf<N, T> {
56 fn get(&self, index: usize) -> Option<&T> {
57 if index >= N || index >= self.len {
58 return None;
59 }
60 self.buf.get(index).maybe_map(Option::as_ref)
61 }
62
63 fn get_mut(&mut self, index: usize) -> Option<&mut T> {
64 if index >= N || index >= self.len {
65 return None;
66 }
67 self.buf.get_mut(index).maybe_map(Option::as_mut)
68 }
69
70 fn capacity(&self) -> usize {
71 N
72 }
73
74 fn len(&self) -> usize {
75 self.len
76 }
77
78 fn clear(&mut self) {
79 self.len = 0
80 }
81
82 fn front(&self) -> Option<&T> {
83 self.get(0)
84 }
85
86 fn front_mut(&mut self) -> Option<&mut T> {
87 self.get_mut(0)
88 }
89
90 fn back(&self) -> Option<&T> {
91 if N == 0 || self.len == 0 {
92 return None;
93 }
94 self.get(self.len - 1)
95 }
96
97 fn back_mut(&mut self) -> Option<&mut T> {
98 if N == 0 || self.len == 0 {
99 return None;
100 }
101 self.get_mut(self.len - 1)
102 }
103
104 fn pop_front(&mut self) -> Option<T> {
105 if N == 0 || self.len == 0 {
106 return None;
107 }
108 let out = self.buf[0].take();
109 for idx in 1..self.len {
110 self.buf[idx - 1] = self.buf[idx].take();
111 }
112 self.len -= 1;
113 out
114 }
115
116 fn pop_back(&mut self) -> Option<T> {
117 if N == 0 || self.len == 0 {
118 return None;
119 }
120 let idx = self.len - 1;
121 self.len -= 1;
122 self.buf[idx].take()
123 }
124
125 fn push_front(&mut self, value: T) -> Result<(), T> {
126 if N == 0 || self.len == N {
127 return Err(value);
128 }
129 for idx in 0..self.len {
130 self.buf[idx + 1] = self.buf[idx].take();
131 }
132 self.buf[0] = Some(value);
133 self.len += 1;
134 Ok(())
135 }
136
137 fn push_back(&mut self, value: T) -> Result<(), T> {
138 if N == 0 || self.len == N {
139 return Err(value);
140 }
141 self.buf[self.len] = Some(value);
142 self.len += 1;
143 Ok(())
144 }
145}
146
147#[allow(clippy::panic)]
148impl<const N: usize, T> Index<usize> for FixedBuf<N, T>
149where
150 T: Default,
151{
152 type Output = T;
153
154 fn index(&self, index: usize) -> &Self::Output {
155 assert!(index < self.len, "index {index} >= len {}", self.len);
156 let Some(Some(val)) = self.buf.get(index) else {
157 panic!("expected value at offset {index} but was empty!");
158 };
159 val
160 }
161}
162#[allow(clippy::panic)]
163impl<const N: usize, T> IndexMut<usize> for FixedBuf<N, T>
164where
165 T: Default,
166{
167 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
168 assert!(index < N, "index {index} >= capacity {N}");
169 if self.buf[index].is_none() {
170 self.len += 1;
171 self.buf[index] = Some(Default::default());
172 }
173 self.buf[index].as_mut().unwrap()
174 }
175}
176
177impl<const N: usize, T: Sized + Default + Copy> FixedBuf<N, T> {
178 pub fn into_buf_default(&mut self) -> [T; N] {
179 let mut out = [T::default(); N];
180 for (i, o) in zip(self.buf.iter_mut(), out.iter_mut()) {
181 if let Some(val) = i.take() {
182 *o = val;
183 }
184 }
185 self.clear();
186 out
187 }
188}
189impl<const N: usize, T: Sized> FixedBuf<N, T> {
190 pub fn iter(&self) -> FixedBufIter<N, T> {
191 FixedBufIter { buf: self, idx: 0 }
192 }
193}
194impl<const N: usize, T: Sized + WriteToBEBits> FixedBuf<N, T> {
195 pub fn write_to<B: MutBits + ?Sized>(&self, out: &mut B) -> Result<usize, BitsError> {
196 for v in self.iter() {
197 WriteToBEBits::write_be_to(v, out)?;
198 }
199 Ok(self.len)
200 }
201}
202pub struct FixedBufIter<'a, const N: usize, T: Sized> {
203 buf: &'a FixedBuf<N, T>,
204 idx: usize,
205}
206
207impl<'a, const N: usize, T: Sized> Iterator for FixedBufIter<'a, N, T> {
208 type Item = &'a T;
209 fn next(&mut self) -> Option<Self::Item> {
210 if let Some(val) = self.buf.get(self.idx) {
211 self.idx += 1;
212 return Some(val);
213 }
214 None
215 }
216}
217impl<const N: usize, T: Sized> DoubleEndedIterator for FixedBufIter<'_, N, T> {
218 fn next_back(&mut self) -> Option<Self::Item> {
219 if self.idx >= self.buf.len {
220 return None;
221 }
222 let idx = self.buf.len().saturating_sub(self.idx).saturating_sub(1);
223
224 self.idx += 1;
225 if let Some(val) = self.buf.get(idx) {
226 return Some(val);
227 }
228 None
229 }
230}
231impl<const N: usize, T: Sized> ExactSizeIterator for FixedBufIter<'_, N, T> {
232 fn len(&self) -> usize {
233 self.buf.len()
234 }
235}
236
237pub struct FixedBufIterMut<'a, const N: usize, T: Sized> {
238 buf: &'a mut FixedBuf<N, T>,
239 idx: usize,
240}
241
242impl<const N: usize, T: Sized> LendingIterator for FixedBufIterMut<'_, N, T> {
243 type Item<'b>
244 = &'b mut T
245 where
246 Self: 'b;
247
248 fn next_ref(&mut self) -> Option<Self::Item<'_>> {
249 if let Some(val) = self.buf.get_mut(self.idx) {
250 self.idx += 1;
251 return Some(val);
252 }
253 None
254 }
255}
256
257impl<const N: usize> MutBits for &mut FixedBuf<N, u8> {
258 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
259 if self.push_back(val).is_err() {
260 return Err(BitsErrorKind::UnexpectedEof.into());
261 }
262 Ok(())
263 }
264}
265impl<const N: usize> MutBits for FixedBuf<N, u8> {
266 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
267 if self.push_back(val).is_err() {
268 return Err(BitsErrorKind::UnexpectedEof.into());
269 }
270 Ok(())
271 }
272}