diff --git a/apps/system/components/DebugConsole/kata-debug-console/Cargo.toml b/apps/system/components/DebugConsole/kata-debug-console/Cargo.toml index 55fbe48..8e8a8d5 100644 --- a/apps/system/components/DebugConsole/kata-debug-console/Cargo.toml +++ b/apps/system/components/DebugConsole/kata-debug-console/Cargo.toml @@ -8,6 +8,7 @@ description = "Kata OS DebugConsole" [dependencies] panic-halt = "0.2.0" kata-allocator = { path = "../kata-allocator" } +kata-io = { path = "../kata-io" } kata-logger = { path = "../kata-logger" } kata-panic = { path = "../kata-panic" } kata-shell = { path = "../kata-shell" } diff --git a/apps/system/components/DebugConsole/kata-debug-console/src/run.rs b/apps/system/components/DebugConsole/kata-debug-console/src/run.rs index 043c521..e892ad3 100644 --- a/apps/system/components/DebugConsole/kata-debug-console/src/run.rs +++ b/apps/system/components/DebugConsole/kata-debug-console/src/run.rs @@ -15,6 +15,7 @@ extern crate kata_panic; use kata_allocator; +use kata_io; use kata_logger::KataLogger; use kata_shell; use kata_uart_client; @@ -45,6 +46,6 @@ pub extern "C" fn pre_init() { pub extern "C" fn run() -> ! { trace!("run"); let mut tx = kata_uart_client::Tx::new(); - let mut rx = kata_uart_client::Rx::new(); + let mut rx = kata_io::BufReader::new(kata_uart_client::Rx::new()); kata_shell::repl(&mut tx, &mut rx); } diff --git a/apps/system/components/DebugConsole/kata-io/Cargo.toml b/apps/system/components/DebugConsole/kata-io/Cargo.toml index eaccbe5..ca3c4f0 100644 --- a/apps/system/components/DebugConsole/kata-io/Cargo.toml +++ b/apps/system/components/DebugConsole/kata-io/Cargo.toml @@ -3,3 +3,6 @@ name = "kata-io" version = "0.1.0" authors = ["Matt Harvey "] edition = "2018" + +[dependencies] +memchr = { version = "2.4.1", default-features = false } diff --git a/apps/system/components/DebugConsole/kata-io/src/lib.rs b/apps/system/components/DebugConsole/kata-io/src/lib.rs index f09b1aa..b75d935 100644 --- a/apps/system/components/DebugConsole/kata-io/src/lib.rs +++ b/apps/system/components/DebugConsole/kata-io/src/lib.rs @@ -1,5 +1,9 @@ #![no_std] +extern crate alloc; + +use alloc::boxed::Box; +use alloc::vec::Vec; use core::cmp; #[derive(Debug)] @@ -30,6 +34,38 @@ pub trait Read { } } +/// Partial mimic of std::io::BufRead. +pub trait BufRead: Read { + fn fill_buf(&mut self) -> Result<&[u8]>; + + fn consume(&mut self, amt: usize); + + fn read_until(&mut self, delim: u8, buf: &mut Vec) -> Result { + // Implementation adapted from std::io. + let mut read = 0; + loop { + let (done, used) = { + let available = self.fill_buf()?; + match memchr::memchr(delim, available) { + Some(i) => { + buf.extend_from_slice(&available[..=i]); + (true, i + 1) + } + None => { + buf.extend_from_slice(available); + (false, available.len()) + } + } + }; + self.consume(used); + read += used; + if done || used == 0 { + return Ok(read); + } + } + } +} + /// Partial mimic of std::io::Write. pub trait Write { fn write(&mut self, buf: &[u8]) -> Result; @@ -103,3 +139,70 @@ where (**self).flush() } } + +pub struct BufReader { + inner: R, + buf: Box<[u8]>, + pos: usize, + cap: usize, +} + +impl BufReader { + pub fn new(inner: R) -> BufReader { + const BUFFER_SIZE : usize = 1024; // free to be changed + BufReader { + inner: inner, + buf: Box::new([0u8; BUFFER_SIZE]), + pos: 0, + cap: 0, + } + } + + fn discard_buffer(&mut self) { + // Implementation copied from std::io. + self.pos = 0; + self.cap = 0; + } +} + +impl Read for BufReader { + fn read(&mut self, buf: &mut [u8]) -> Result { + // Implementation copied from std::io. + + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= self.buf.len() { + self.discard_buffer(); + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) + } +} + +impl BufRead for BufReader { + fn fill_buf(&mut self) -> Result<&[u8]> { + // Implementation copied from std::io. + + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + // Branch using `>=` instead of the more correct `==` + // to tell the compiler that the pos..cap slice is always valid. + if self.pos >= self.cap { + debug_assert!(self.pos == self.cap); + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) + } + + fn consume(&mut self, amt: usize) { + // Implementation copied from std::io. + self.pos = cmp::min(self.pos + amt, self.cap); + } +}