oxigdal_embedded/
buffer.rs1use crate::error::{EmbeddedError, Result};
4use core::mem::MaybeUninit;
5
6pub struct FixedBuffer<T, const N: usize> {
8 data: [MaybeUninit<T>; N],
9 len: usize,
10}
11
12impl<T, const N: usize> FixedBuffer<T, N> {
13 pub const fn new() -> Self {
15 Self {
16 data: unsafe { MaybeUninit::uninit().assume_init() },
18 len: 0,
19 }
20 }
21
22 pub const fn capacity(&self) -> usize {
24 N
25 }
26
27 pub const fn len(&self) -> usize {
29 self.len
30 }
31
32 pub const fn is_empty(&self) -> bool {
34 self.len == 0
35 }
36
37 pub const fn is_full(&self) -> bool {
39 self.len >= N
40 }
41
42 pub fn push(&mut self, item: T) -> Result<()> {
48 if self.is_full() {
49 return Err(EmbeddedError::BufferTooSmall {
50 required: 1,
51 available: 0,
52 });
53 }
54
55 self.data[self.len].write(item);
56 self.len += 1;
57 Ok(())
58 }
59
60 pub fn pop(&mut self) -> Result<T> {
66 if self.is_empty() {
67 return Err(EmbeddedError::InvalidParameter);
68 }
69
70 self.len -= 1;
71 let item = unsafe { self.data[self.len].assume_init_read() };
73 Ok(item)
74 }
75
76 pub fn get(&self, index: usize) -> Result<&T> {
82 if index >= self.len {
83 return Err(EmbeddedError::OutOfBounds {
84 index,
85 max: self.len.saturating_sub(1),
86 });
87 }
88
89 let item = unsafe { self.data[index].assume_init_ref() };
91 Ok(item)
92 }
93
94 pub fn get_mut(&mut self, index: usize) -> Result<&mut T> {
100 if index >= self.len {
101 return Err(EmbeddedError::OutOfBounds {
102 index,
103 max: self.len.saturating_sub(1),
104 });
105 }
106
107 let item = unsafe { self.data[index].assume_init_mut() };
109 Ok(item)
110 }
111
112 pub fn clear(&mut self) {
114 for i in 0..self.len {
116 unsafe {
118 self.data[i].assume_init_drop();
119 }
120 }
121 self.len = 0;
122 }
123
124 pub fn as_slice(&self) -> &[T] {
126 unsafe { core::slice::from_raw_parts(self.data.as_ptr().cast(), self.len) }
128 }
129
130 pub fn as_mut_slice(&mut self) -> &mut [T] {
132 unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().cast(), self.len) }
134 }
135
136 pub fn extend_from_slice(&mut self, items: &[T]) -> Result<()>
142 where
143 T: Copy,
144 {
145 if self.len + items.len() > N {
146 return Err(EmbeddedError::BufferTooSmall {
147 required: items.len(),
148 available: N - self.len,
149 });
150 }
151
152 for item in items {
153 self.data[self.len].write(*item);
154 self.len += 1;
155 }
156
157 Ok(())
158 }
159}
160
161impl<T, const N: usize> Default for FixedBuffer<T, N> {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167impl<T, const N: usize> Drop for FixedBuffer<T, N> {
168 fn drop(&mut self) {
169 self.clear();
170 }
171}
172
173pub struct RingBuffer<T: Copy, const N: usize> {
175 data: [T; N],
176 read_pos: usize,
177 write_pos: usize,
178 full: bool,
179}
180
181impl<T: Copy, const N: usize> RingBuffer<T, N> {
182 pub fn new(default: T) -> Self {
184 Self {
185 data: [default; N],
186 read_pos: 0,
187 write_pos: 0,
188 full: false,
189 }
190 }
191
192 pub const fn capacity(&self) -> usize {
194 N
195 }
196
197 pub fn len(&self) -> usize {
199 if self.full {
200 N
201 } else if self.write_pos >= self.read_pos {
202 self.write_pos - self.read_pos
203 } else {
204 N - self.read_pos + self.write_pos
205 }
206 }
207
208 pub fn is_empty(&self) -> bool {
210 !self.full && self.read_pos == self.write_pos
211 }
212
213 pub const fn is_full(&self) -> bool {
215 self.full
216 }
217
218 pub fn write(&mut self, item: T) -> Result<()> {
224 if self.full {
225 return Err(EmbeddedError::BufferTooSmall {
226 required: 1,
227 available: 0,
228 });
229 }
230
231 self.data[self.write_pos] = item;
232 self.write_pos = (self.write_pos + 1) % N;
233
234 if self.write_pos == self.read_pos {
235 self.full = true;
236 }
237
238 Ok(())
239 }
240
241 pub fn read(&mut self) -> Result<T> {
247 if self.is_empty() {
248 return Err(EmbeddedError::InvalidParameter);
249 }
250
251 let item = self.data[self.read_pos];
252 self.read_pos = (self.read_pos + 1) % N;
253 self.full = false;
254
255 Ok(item)
256 }
257
258 pub fn peek(&self) -> Result<T> {
260 if self.is_empty() {
261 return Err(EmbeddedError::InvalidParameter);
262 }
263
264 Ok(self.data[self.read_pos])
265 }
266
267 pub fn clear(&mut self) {
269 self.read_pos = 0;
270 self.write_pos = 0;
271 self.full = false;
272 }
273}
274
275#[repr(C, align(64))]
277pub struct AlignedBuffer<const N: usize> {
278 data: [u8; N],
279}
280
281impl<const N: usize> AlignedBuffer<N> {
282 pub const fn new() -> Self {
284 Self { data: [0u8; N] }
285 }
286
287 pub fn as_slice(&self) -> &[u8] {
289 &self.data
290 }
291
292 pub fn as_mut_slice(&mut self) -> &mut [u8] {
294 &mut self.data
295 }
296
297 pub fn as_ptr(&self) -> *const u8 {
299 self.data.as_ptr()
300 }
301
302 pub fn as_mut_ptr(&mut self) -> *mut u8 {
304 self.data.as_mut_ptr()
305 }
306
307 pub const fn alignment(&self) -> usize {
309 64
310 }
311
312 pub fn verify_alignment(&self) -> bool {
314 self.as_ptr() as usize % 64 == 0
315 }
316}
317
318impl<const N: usize> Default for AlignedBuffer<N> {
319 fn default() -> Self {
320 Self::new()
321 }
322}
323
324#[cfg(test)]
325mod tests {
326 use super::*;
327
328 #[test]
329 fn test_fixed_buffer() {
330 let mut buffer = FixedBuffer::<u32, 8>::new();
331 assert_eq!(buffer.len(), 0);
332 assert!(buffer.is_empty());
333
334 buffer.push(1).expect("push failed");
335 buffer.push(2).expect("push failed");
336 assert_eq!(buffer.len(), 2);
337
338 assert_eq!(*buffer.get(0).expect("get failed"), 1);
339 assert_eq!(*buffer.get(1).expect("get failed"), 2);
340
341 let item = buffer.pop().expect("pop failed");
342 assert_eq!(item, 2);
343 assert_eq!(buffer.len(), 1);
344 }
345
346 #[test]
347 fn test_fixed_buffer_overflow() {
348 let mut buffer = FixedBuffer::<u32, 2>::new();
349 buffer.push(1).expect("push failed");
350 buffer.push(2).expect("push failed");
351
352 let result = buffer.push(3);
353 assert!(matches!(result, Err(EmbeddedError::BufferTooSmall { .. })));
354 }
355
356 #[test]
357 fn test_ring_buffer() {
358 let mut buffer = RingBuffer::<u32, 4>::new(0);
359 assert!(buffer.is_empty());
360
361 buffer.write(1).expect("write failed");
362 buffer.write(2).expect("write failed");
363 assert_eq!(buffer.len(), 2);
364
365 let item = buffer.read().expect("read failed");
366 assert_eq!(item, 1);
367
368 buffer.write(3).expect("write failed");
369 buffer.write(4).expect("write failed");
370 buffer.write(5).expect("write failed");
371
372 assert!(buffer.is_full());
373 assert!(buffer.write(6).is_err());
374 }
375
376 #[test]
377 fn test_aligned_buffer() {
378 let buffer = AlignedBuffer::<256>::new();
379 assert_eq!(buffer.alignment(), 64);
380 assert!(buffer.verify_alignment());
381 }
382}