opentitanlib/io/console/
buf.rs1use std::sync::Mutex;
6use std::task::{Context, Poll, ready};
7
8use anyhow::Result;
9
10use super::ConsoleDevice;
11use crate::io::middleware::{ConsoleMiddleware, Middleware, UartMiddleware};
12use crate::io::uart::Uart;
13
14pub struct Buffered<T> {
16 inner: T,
17 buffer: Mutex<Inner>,
18}
19
20struct Inner {
21 buffer: Box<[u8; 256]>,
22 len: usize,
23 offset: usize,
24}
25
26impl<T> Buffered<T> {
27 pub fn new(inner: T) -> Self {
28 Self {
29 inner,
30 buffer: Mutex::new(Inner {
31 buffer: vec![0; 256].try_into().unwrap(),
32 len: 0,
33 offset: 0,
34 }),
35 }
36 }
37}
38
39impl<T: ConsoleDevice> Middleware for Buffered<T> {
40 type Inner = T;
41 fn inner(&self) -> &T {
42 &self.inner
43 }
44}
45
46impl<T: ConsoleDevice> ConsoleMiddleware for Buffered<T> {
47 fn poll_read_impl(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
48 let mut buffer = self.buffer.lock().unwrap();
49
50 loop {
51 if buffer.len != 0 {
52 let copy_len = std::cmp::min(buffer.len, buf.len());
53 buf[..copy_len].copy_from_slice(&buffer.buffer[buffer.offset..][..copy_len]);
54 buffer.offset += copy_len;
55 buffer.len -= copy_len;
56 return Poll::Ready(Ok(copy_len));
57 }
58
59 if buf.len() >= buffer.buffer.len() {
60 return self.inner.poll_read(cx, buf);
61 }
62
63 buffer.len = ready!(self.inner.poll_read(cx, &mut buffer.buffer[..]))?;
64 buffer.offset = 0;
65 }
66 }
67}
68
69impl<T: Uart> UartMiddleware for Buffered<T> {
70 fn clear_rx_buffer_impl(&self) -> Result<()> {
71 let mut buffer = self.buffer.lock().unwrap();
72 buffer.offset = 0;
73 buffer.len = 0;
74
75 self.inner.clear_rx_buffer()?;
76 Ok(())
77 }
78}