Makes ZMODEM crate use BufRead

Using a buffered reader instead of the byte-at-a-time implementation
avoids doing a syscall for each byte.

Change-Id: Ia7bc42e4836593f358ff964962c910f8c94b6f8e
GitOrigin-RevId: e70697d398b07d6de6f03d1d0a4b5204139bc59a
This commit is contained in:
Matt Harvey 2021-09-26 15:58:41 -07:00 committed by Sam Leffler
parent a91f8f7916
commit c26d79fff8
5 changed files with 46 additions and 54 deletions

View File

@ -116,30 +116,6 @@ impl Read for &[u8] {
}
}
/// Forwarding implementation of Read for &mut
impl<'a, T: ?Sized> Read for &'a mut T
where
T: Read,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
(**self).read(buf)
}
}
/// Forwarding implementation of Write for &mut
impl<'a, T: ?Sized> Write for &'a mut T
where
T: Write,
{
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> Result<()> {
(**self).flush()
}
}
pub struct BufReader<R> {
inner: R,
buf: Box<[u8]>,
@ -206,3 +182,41 @@ impl<R: Read> BufRead for BufReader<R> {
self.pos = cmp::min(self.pos + amt, self.cap);
}
}
/// Forwarding implementation of Read for &mut
impl<'a, T: ?Sized> Read for &'a mut T
where
T: Read,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
(**self).read(buf)
}
}
/// Forwarding implementation of BufRead for &mut
impl<'a, T: ?Sized> BufRead for &'a mut T
where
T: BufRead,
{
fn fill_buf(&mut self) -> Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
/// Forwarding implementation of Write for &mut
impl<'a, T: ?Sized> Write for &'a mut T
where
T: Write,
{
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> Result<()> {
(**self).flush()
}
}

View File

@ -66,7 +66,7 @@ impl From<io::Error> for CommandError {
}
/// Read-eval-print loop for the DebugConsole command line interface.
pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
pub fn repl<T: io::BufRead>(output: &mut dyn io::Write, input: &mut T) -> ! {
let mut line_reader = LineReader::new();
loop {
const PROMPT: &str = "KATA> ";
@ -84,7 +84,7 @@ pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
///
/// The line is split on whitespace. The first token is the command; the
/// remaining tokens are the arguments.
fn dispatch_command(cmdline: &str, input: &mut dyn io::Read, output: &mut dyn io::Write) {
fn dispatch_command(cmdline: &str, input: &mut dyn io::BufRead, output: &mut dyn io::Write) {
let mut args = cmdline.split_ascii_whitespace();
match args.nth(0) {
Some(command) => {
@ -193,7 +193,7 @@ fn loglevel_command(
/// Implements a command to receive a blob using ZMODEM.
fn rz_command(
input: &mut dyn io::Read,
input: &mut dyn io::BufRead,
mut output: &mut dyn io::Write,
) -> Result<(), CommandError> {
let upload = rz::rz(input, &mut output)?;

View File

@ -43,7 +43,7 @@ impl io::Write for Upload {
}
/// Receives using ZMODEM and wraps the result as an Upload.
pub fn rz<R: io::Read, W: io::Write>(r: R, w: W) -> Result<Upload, io::Error> {
pub fn rz<R: io::BufRead, W: io::Write>(r: R, w: W) -> Result<Upload, io::Error> {
let mut upload = Upload::new();
zmodem::recv::recv(r, w, &mut upload)?;
Ok(upload)

View File

@ -106,37 +106,15 @@ where
Ok(())
}
/// Read into buf until and including the byte delim
///
/// This is a one-off implementation of a method of io::BufRead that the
/// original lexxvir/zmodem had used. (So far kata_io is deferring implementing
/// buffering to validate it will become needed in more places.)
fn read_until<R>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> io::Result<usize>
where
R: io::Read,
{
let mut n = 0usize;
loop {
let b = read_byte(r)?;
buf.push(b);
n += 1;
if b == delim {
break;
}
}
Ok(n)
}
/// Receives sequence: <escaped data> ZLDE ZCRC* <CRC bytes>
/// Unescapes sequencies such as 'ZLDE <escaped byte>'
/// If Ok returns <unescaped data> in buf and ZCRC* byte as return value
pub fn recv_zlde_frame<R>(header: u8, r: &mut R, buf: &mut Vec<u8>) -> io::Result<Option<u8>>
where
R: io::Read,
R: io::BufRead,
{
loop {
read_until(r, ZLDE, buf)?;
r.read_until(ZLDE, buf)?;
let b = read_byte(r)?;
if !is_escaped(b) {
@ -173,7 +151,7 @@ pub fn recv_data<CI, CO, DO>(
data_out: &mut DO,
) -> io::Result<bool>
where
CI: io::Read,
CI: io::BufRead,
CO: io::Write,
DO: io::Write,
{

View File

@ -59,7 +59,7 @@ pub fn recv<CI, CO, DO>(
mut data_out: DO,
) -> io::Result<usize>
where
CI: io::Read,
CI: io::BufRead,
CO: io::Write,
DO: io::Write,
{