fifo.rs 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. use core::mem::MaybeUninit;
  2. /// Size of the FIFO buffer.
  3. const FIFO_SIZE: usize = 16;
  4. #[derive(Debug)]
  5. pub enum FifoError {
  6. Empty,
  7. Full,
  8. }
  9. /// A fixed-size FIFO (First In First Out) queue implementation.
  10. pub struct Fifo<T: Copy + Clone> {
  11. data: [MaybeUninit<T>; FIFO_SIZE],
  12. head: usize,
  13. tail: usize,
  14. count: usize,
  15. }
  16. impl<T: Copy + Clone> Fifo<T> {
  17. #[inline]
  18. pub fn new() -> Self {
  19. // Initialize array with uninitialized values
  20. let data = [MaybeUninit::uninit(); FIFO_SIZE];
  21. Self {
  22. data,
  23. head: 0,
  24. tail: 0,
  25. count: 0,
  26. }
  27. }
  28. #[inline]
  29. pub fn is_full(&self) -> bool {
  30. self.count == FIFO_SIZE
  31. }
  32. #[inline]
  33. pub fn is_empty(&self) -> bool {
  34. self.count == 0
  35. }
  36. pub fn push(&mut self, element: T) -> Result<(), FifoError> {
  37. if self.is_full() {
  38. return Err(FifoError::Full);
  39. }
  40. // Write element and update tail position
  41. self.data[self.tail].write(element);
  42. self.tail = (self.tail + 1) % FIFO_SIZE;
  43. self.count += 1;
  44. Ok(())
  45. }
  46. pub fn pop(&mut self) -> Result<T, FifoError> {
  47. if self.is_empty() {
  48. return Err(FifoError::Empty);
  49. }
  50. // unsafe: Take ownership of element at head
  51. let element = unsafe { self.data[self.head].assume_init_read() };
  52. // Update head position
  53. self.head = (self.head + 1) % FIFO_SIZE;
  54. self.count -= 1;
  55. Ok(element)
  56. }
  57. }