sel4_driver_interfaces/serial/
write_buffered.rs

1//
2// Copyright 2024, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7use embedded_hal_nb::nb;
8use embedded_hal_nb::serial;
9use heapless::Deque;
10
11#[derive(Debug, Clone)]
12pub struct WriteBuffered<T, const WRITE_BUF_SIZE: usize = 256> {
13    unbuffered: T,
14    write_buffer: Deque<u8, WRITE_BUF_SIZE>,
15}
16
17impl<T, const WRITE_BUF_SIZE: usize> WriteBuffered<T, WRITE_BUF_SIZE> {
18    pub fn new(unbuffered: T) -> Self {
19        Self {
20            unbuffered,
21            write_buffer: Deque::new(),
22        }
23    }
24
25    fn enqueue<E>(&mut self, v: u8) -> nb::Result<(), E> {
26        match self.write_buffer.push_back(v) {
27            Ok(()) => Ok(()),
28            Err(_) => Err(nb::Error::WouldBlock),
29        }
30    }
31
32    fn enqueue_if_would_block<E>(&mut self, err: nb::Error<E>, v: u8) -> nb::Result<(), E> {
33        match err {
34            err @ nb::Error::Other(_) => Err(err),
35            nb::Error::WouldBlock => self.enqueue(v),
36        }
37    }
38}
39
40impl<T: serial::Write<u8>, const WRITE_BUF_SIZE: usize> WriteBuffered<T, WRITE_BUF_SIZE> {
41    fn write_entire_buffer(&mut self) -> nb::Result<(), <Self as serial::ErrorType>::Error> {
42        loop {
43            if let Some(v) = self.write_buffer.front() {
44                if let err @ Err(_) = self.unbuffered.write(*v) {
45                    break err;
46                }
47            } else {
48                break Ok(());
49            }
50            self.write_buffer.pop_front().unwrap();
51        }
52    }
53}
54
55impl<T: serial::ErrorType, const WRITE_BUF_SIZE: usize> serial::ErrorType
56    for WriteBuffered<T, WRITE_BUF_SIZE>
57{
58    type Error = T::Error;
59}
60
61impl<T: serial::Read, const WRITE_BUF_SIZE: usize> serial::Read<u8>
62    for WriteBuffered<T, WRITE_BUF_SIZE>
63{
64    fn read(&mut self) -> nb::Result<u8, Self::Error> {
65        self.unbuffered.read()
66    }
67}
68
69impl<T: serial::Write, const WRITE_BUF_SIZE: usize> serial::Write<u8>
70    for WriteBuffered<T, WRITE_BUF_SIZE>
71{
72    fn write(&mut self, v: u8) -> nb::Result<(), Self::Error> {
73        match self.write_entire_buffer() {
74            Err(err) => self.enqueue_if_would_block(err, v),
75            Ok(()) => match self.unbuffered.write(v) {
76                Err(err) => self.enqueue_if_would_block(err, v),
77                Ok(()) => Ok(()),
78            },
79        }
80    }
81
82    fn flush(&mut self) -> nb::Result<(), Self::Error> {
83        self.write_entire_buffer()?;
84        self.unbuffered.flush()
85    }
86}