Skip to main content

irox_tools/buf/
array.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5#![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}