// Copyright (c) 2026 taitep // SPDX-License-Identifier: BSD-2-Clause // // This file is part of TRVE (https://gitea.taitep.se/taitep/trve) // See LICENSE file in the project root for full license text. use std::io::{self, Read, Write}; pub struct UartFifo { buf: [u8; CAP], head: usize, tail: usize, len: usize, } impl UartFifo { pub fn pop_single_byte(&mut self) -> Option { if self.is_empty() { return None; } let value = self.buf[self.tail]; self.advance_read(1); Some(value) } pub fn push_single_byte(&mut self, value: u8) -> bool { if self.is_full() { return false; } self.buf[self.head] = value; self.advance_write(1); true } pub fn is_empty(&self) -> bool { self.len == 0 } pub fn is_full(&self) -> bool { self.len == CAP } fn write_slice(&mut self) -> &mut [u8] { if self.is_full() { return &mut []; } if self.head >= self.tail { &mut self.buf[self.head..] } else { &mut self.buf[self.head..self.tail] } } fn advance_write(&mut self, n: usize) { debug_assert!(n <= CAP - self.len); self.head = (self.head + n) % CAP; self.len += n; } fn read_slice(&self) -> &[u8] { if self.is_empty() { return &[]; } if self.tail < self.head { &self.buf[self.tail..self.head] } else { &self.buf[self.tail..] } } fn advance_read(&mut self, n: usize) { debug_assert!(n <= self.len); self.tail = (self.tail + n) % CAP; self.len -= n; } pub fn read_from(&mut self, reader: &mut R) -> io::Result { let slice = self.write_slice(); if slice.is_empty() { return Ok(0); } let n = reader.read(slice)?; self.advance_write(n); Ok(n) } pub fn write_to(&mut self, writer: &mut W) -> io::Result { let slice = self.read_slice(); if slice.is_empty() { return Ok(0); } let n = writer.write(slice)?; self.advance_read(n); Ok(n) } } impl Default for UartFifo { fn default() -> Self { UartFifo { buf: [0; SIZE], head: 0, tail: 0, len: 0, } } }