mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-08-11 18:12:41 +00:00
Implements BufRead in kata_io
Reading one byte at a time in a loop causes excessive syscalls. For example, ZMODEM needs to do this when finding the end of each frame. This change copies parts of std::io needed to wrap a Read in a BufReader so that the read will be done eagerly. It enables buffered UART reads for the whole DebugConsole at the point where its single Read object is initialized. Change-Id: I19935ca02333bc74d9b581d384a1854968ac5329 GitOrigin-RevId: 1aa80e036561a6a18e79dbf28bcab240efe80cd1
This commit is contained in:
parent
d70003982c
commit
4faa2e4c82
@ -8,6 +8,7 @@ description = "Kata OS DebugConsole"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
panic-halt = "0.2.0"
|
panic-halt = "0.2.0"
|
||||||
kata-allocator = { path = "../kata-allocator" }
|
kata-allocator = { path = "../kata-allocator" }
|
||||||
|
kata-io = { path = "../kata-io" }
|
||||||
kata-logger = { path = "../kata-logger" }
|
kata-logger = { path = "../kata-logger" }
|
||||||
kata-panic = { path = "../kata-panic" }
|
kata-panic = { path = "../kata-panic" }
|
||||||
kata-shell = { path = "../kata-shell" }
|
kata-shell = { path = "../kata-shell" }
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
extern crate kata_panic;
|
extern crate kata_panic;
|
||||||
|
|
||||||
use kata_allocator;
|
use kata_allocator;
|
||||||
|
use kata_io;
|
||||||
use kata_logger::KataLogger;
|
use kata_logger::KataLogger;
|
||||||
use kata_shell;
|
use kata_shell;
|
||||||
use kata_uart_client;
|
use kata_uart_client;
|
||||||
@ -45,6 +46,6 @@ pub extern "C" fn pre_init() {
|
|||||||
pub extern "C" fn run() -> ! {
|
pub extern "C" fn run() -> ! {
|
||||||
trace!("run");
|
trace!("run");
|
||||||
let mut tx = kata_uart_client::Tx::new();
|
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);
|
kata_shell::repl(&mut tx, &mut rx);
|
||||||
}
|
}
|
||||||
|
@ -3,3 +3,6 @@ name = "kata-io"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
memchr = { version = "2.4.1", default-features = false }
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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<u8>) -> Result<usize> {
|
||||||
|
// 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.
|
/// Partial mimic of std::io::Write.
|
||||||
pub trait Write {
|
pub trait Write {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
||||||
@ -103,3 +139,70 @@ where
|
|||||||
(**self).flush()
|
(**self).flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BufReader<R> {
|
||||||
|
inner: R,
|
||||||
|
buf: Box<[u8]>,
|
||||||
|
pos: usize,
|
||||||
|
cap: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read> BufReader<R> {
|
||||||
|
pub fn new(inner: R) -> BufReader<R> {
|
||||||
|
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<R: Read> Read for BufReader<R> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
// 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<R: Read> BufRead for BufReader<R> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user