opentitanlib/io/console/
logged.rs1use std::io::Write;
6use std::sync::Mutex;
7use std::task::{Context, Poll, ready};
8use std::time::SystemTime;
9
10use anyhow::Result;
11
12use super::ConsoleDevice;
13use crate::io::middleware::{ConsoleMiddleware, Middleware, UartMiddleware};
14use crate::io::uart::Uart;
15
16pub struct Logged<T> {
18 inner: T,
19 newline: Mutex<bool>,
21}
22
23impl<T> Logged<T> {
24 pub fn new(inner: T) -> Logged<T> {
25 Self {
26 inner,
27 newline: Mutex::new(true),
28 }
29 }
30}
31
32impl<T: ConsoleDevice> Middleware for Logged<T> {
33 type Inner = T;
34 fn inner(&self) -> &T {
35 &self.inner
36 }
37}
38
39impl<T: ConsoleDevice> ConsoleMiddleware for Logged<T> {
40 fn poll_read_impl(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
41 let mut newline = self.newline.lock().unwrap();
43 let len = ready!(self.inner.poll_read(cx, buf))?;
44
45 let mut stdout = std::io::stdout().lock();
46 for ch in buf[..len].iter().copied() {
47 if *newline {
48 let t = humantime::format_rfc3339_millis(SystemTime::now());
49 stdout.write_fmt(format_args!("[{} console]", t))?;
50 }
51
52 *newline = ch == b'\n';
53
54 stdout.write_all(std::slice::from_ref(&ch))?;
55 }
56 stdout.flush()?;
57
58 Poll::Ready(Ok(len))
59 }
60}
61
62impl<T: Uart> UartMiddleware for Logged<T> {
63 fn clear_rx_buffer_impl(&self) -> Result<()> {
64 *self.newline.lock().unwrap() = true;
65 self.inner.clear_rx_buffer()
66 }
67}