1#![allow(clippy::indexing_slicing)]
6
7use core::ops::{Index, IndexMut};
8use irox_bits::{Error, ErrorKind, MutBits};
9
10pub type U32ArrayBuf<const N: usize> = ArrayBuf<N, 4, u32>;
11pub type U64ArrayBuf<const N: usize> = ArrayBuf<N, 8, u64>;
12#[derive(Clone)]
13pub struct ArrayBuf<const N: usize, const O: usize, T: Default + Copy + Sized> {
14 buf: [T; N],
15 b2: [u8; O],
16 b2_used: usize,
17 size: usize,
18}
19impl<const N: usize, const O: usize, T: Default + Copy> Default for ArrayBuf<N, O, T> {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24impl<const N: usize, const O: usize, T: Default + Copy> ArrayBuf<N, O, T> {
25 pub fn new() -> Self {
26 Self {
27 buf: [T::default(); N],
28 b2: [0u8; O],
29 size: 0,
30 b2_used: 0,
31 }
32 }
33 pub fn len(&self) -> usize {
34 self.size
35 }
36 pub fn is_empty(&self) -> bool {
37 self.size == 0
38 }
39 pub fn rem_align(&self) -> usize {
40 O - self.b2_used
41 }
42}
43
44impl<const N: usize> ArrayBuf<N, 4, u32> {
45 pub fn push_back(&mut self, val: u8) -> Result<(), Error> {
46 self.write_u8(val)
47 }
48 pub fn is_full(&self) -> bool {
49 self.size == N
50 }
51
52 pub fn push_prim(&mut self, val: u32) -> Result<(), Error> {
53 let size = self.size;
54 if size == N {
55 return Err(ErrorKind::OutOfMemory.into());
56 }
57 self.buf[size] = val;
58 self.size += 1;
59 Ok(())
60 }
61 pub fn write_le_u8(&mut self, val: u8) -> Result<(), Error> {
62 let size = self.size;
63 if size == N {
64 return Err(ErrorKind::OutOfMemory.into());
65 }
66 self.b2[self.b2_used] = val;
67 self.b2_used += 1;
68
69 if self.b2_used >= 4 {
70 self.b2_used = 0;
71 self.buf[size] = u32::from_le_bytes(self.b2);
72 self.size += 1;
73 }
74 Ok(())
75 }
76 pub fn take_le_buf(&mut self) -> [u32; N] {
77 if self.b2_used > 0 {
78 self.b2[self.b2_used..].fill(0);
79 self.b2_used = 0;
80 self.buf[self.size] = u32::from_le_bytes(self.b2);
81 }
82 self.size = 0;
83 let out = self.buf;
84 self.buf.fill(0);
85 out
86 }
87 pub fn take_be_buf(&mut self) -> [u32; N] {
88 if self.b2_used > 0 {
89 self.b2[self.b2_used..].fill(0);
90 self.b2_used = 0;
91 self.buf[self.size] = u32::from_be_bytes(self.b2);
92 }
93 self.size = 0;
94 let out = self.buf;
95 self.buf.fill(0);
96 out
97 }
98}
99
100impl<const N: usize> MutBits for ArrayBuf<N, 4, u32> {
101 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
102 let size = self.size;
103 if size == N {
104 return Err(ErrorKind::OutOfMemory.into());
105 }
106 self.b2[self.b2_used] = val;
107 self.b2_used += 1;
108
109 if self.b2_used >= 4 {
110 self.b2_used = 0;
111 self.buf[self.size] = u32::from_be_bytes(self.b2);
112 self.size += 1;
113 self.b2.fill(0);
114 }
115 Ok(())
116 }
117
118 fn write_be_u32(&mut self, val: u32) -> Result<(), Error> {
119 let size = self.size;
120 if size == N {
121 return Err(ErrorKind::OutOfMemory.into());
122 }
123 self.buf[self.size] = val;
124 self.size += 1;
125 Ok(())
126 }
127}
128
129impl<const N: usize, const O: usize> Index<usize> for ArrayBuf<N, O, u32> {
130 type Output = u32;
131
132 fn index(&self, index: usize) -> &Self::Output {
133 &self.buf[index]
134 }
135}
136
137impl<const N: usize, const O: usize> IndexMut<usize> for ArrayBuf<N, O, u32> {
138 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
139 &mut self.buf[index]
140 }
141}
142
143impl<const N: usize> ArrayBuf<N, 8, u64> {
144 pub fn push_back(&mut self, val: u8) -> Result<(), Error> {
145 self.write_u8(val)
146 }
147 pub fn is_full(&self) -> bool {
148 self.size == N
149 }
150
151 pub fn push_prim(&mut self, val: u64) -> Result<(), Error> {
152 let size = self.size;
153 if size == N {
154 return Err(ErrorKind::OutOfMemory.into());
155 }
156 self.buf[self.size] = val;
157 self.size += 1;
158 Ok(())
159 }
160 pub fn write_le_u8(&mut self, val: u8) -> Result<(), Error> {
161 let size = self.size;
162 if size == N {
163 return Err(ErrorKind::OutOfMemory.into());
164 }
165 self.b2[self.b2_used] = val;
166 self.b2_used += 1;
167
168 if self.b2_used >= 8 {
169 self.b2_used = 0;
170 self.buf[self.size] = u64::from_le_bytes(self.b2);
171 self.size += 1;
172 }
173 Ok(())
174 }
175 pub fn take_le_buf(&mut self) -> [u64; N] {
176 if self.b2_used > 0 {
177 self.b2[self.b2_used..].fill(0);
178 self.b2_used = 0;
179 self.buf[self.size] = u64::from_le_bytes(self.b2);
180 }
181 self.size = 0;
182 let out = self.buf;
183 self.buf.fill(0);
184 out
185 }
186 pub fn take_be_buf(&mut self) -> [u64; N] {
187 if self.b2_used > 0 {
188 self.b2[self.b2_used..].fill(0);
189 self.b2_used = 0;
190 self.buf[self.size] = u64::from_be_bytes(self.b2);
191 }
192 self.size = 0;
193 let out = self.buf;
194 self.buf.fill(0);
195 out
196 }
197}
198
199impl<const N: usize> MutBits for ArrayBuf<N, 8, u64> {
200 fn write_u8(&mut self, val: u8) -> Result<(), Error> {
201 let size = self.size;
202 if size == N {
203 return Err(ErrorKind::OutOfMemory.into());
204 }
205 self.b2[self.b2_used] = val;
206 self.b2_used += 1;
207
208 if self.b2_used >= 8 {
209 self.b2_used = 0;
210 self.buf[self.size] = u64::from_be_bytes(self.b2);
211 self.size += 1;
212 self.b2.fill(0);
213 }
214 Ok(())
215 }
216
217 fn write_be_u64(&mut self, val: u64) -> Result<(), Error> {
218 let size = self.size;
219 if size == N {
220 return Err(ErrorKind::OutOfMemory.into());
221 }
222 self.buf[self.size] = val;
223 self.size += 1;
224 Ok(())
225 }
226}
227
228impl<const N: usize, const O: usize> Index<usize> for ArrayBuf<N, O, u64> {
229 type Output = u64;
230
231 fn index(&self, index: usize) -> &Self::Output {
232 &self.buf[index]
233 }
234}
235
236impl<const N: usize, const O: usize> IndexMut<usize> for ArrayBuf<N, O, u64> {
237 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
238 &mut self.buf[index]
239 }
240}