mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-08-16 04:13:37 +00:00
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:
parent
a91f8f7916
commit
c26d79fff8
@ -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> {
|
pub struct BufReader<R> {
|
||||||
inner: R,
|
inner: R,
|
||||||
buf: Box<[u8]>,
|
buf: Box<[u8]>,
|
||||||
@ -206,3 +182,41 @@ impl<R: Read> BufRead for BufReader<R> {
|
|||||||
self.pos = cmp::min(self.pos + amt, self.cap);
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -66,7 +66,7 @@ impl From<io::Error> for CommandError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read-eval-print loop for the DebugConsole command line interface.
|
/// 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();
|
let mut line_reader = LineReader::new();
|
||||||
loop {
|
loop {
|
||||||
const PROMPT: &str = "KATA> ";
|
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
|
/// The line is split on whitespace. The first token is the command; the
|
||||||
/// remaining tokens are the arguments.
|
/// 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();
|
let mut args = cmdline.split_ascii_whitespace();
|
||||||
match args.nth(0) {
|
match args.nth(0) {
|
||||||
Some(command) => {
|
Some(command) => {
|
||||||
@ -193,7 +193,7 @@ fn loglevel_command(
|
|||||||
|
|
||||||
/// Implements a command to receive a blob using ZMODEM.
|
/// Implements a command to receive a blob using ZMODEM.
|
||||||
fn rz_command(
|
fn rz_command(
|
||||||
input: &mut dyn io::Read,
|
input: &mut dyn io::BufRead,
|
||||||
mut output: &mut dyn io::Write,
|
mut output: &mut dyn io::Write,
|
||||||
) -> Result<(), CommandError> {
|
) -> Result<(), CommandError> {
|
||||||
let upload = rz::rz(input, &mut output)?;
|
let upload = rz::rz(input, &mut output)?;
|
||||||
|
@ -43,7 +43,7 @@ impl io::Write for Upload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Receives using ZMODEM and wraps the result as an 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();
|
let mut upload = Upload::new();
|
||||||
zmodem::recv::recv(r, w, &mut upload)?;
|
zmodem::recv::recv(r, w, &mut upload)?;
|
||||||
Ok(upload)
|
Ok(upload)
|
||||||
|
@ -106,37 +106,15 @@ where
|
|||||||
Ok(())
|
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>
|
/// Receives sequence: <escaped data> ZLDE ZCRC* <CRC bytes>
|
||||||
/// Unescapes sequencies such as 'ZLDE <escaped byte>'
|
/// Unescapes sequencies such as 'ZLDE <escaped byte>'
|
||||||
/// If Ok returns <unescaped data> in buf and ZCRC* byte as return value
|
/// 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>>
|
pub fn recv_zlde_frame<R>(header: u8, r: &mut R, buf: &mut Vec<u8>) -> io::Result<Option<u8>>
|
||||||
where
|
where
|
||||||
R: io::Read,
|
R: io::BufRead,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
read_until(r, ZLDE, buf)?;
|
r.read_until(ZLDE, buf)?;
|
||||||
let b = read_byte(r)?;
|
let b = read_byte(r)?;
|
||||||
|
|
||||||
if !is_escaped(b) {
|
if !is_escaped(b) {
|
||||||
@ -173,7 +151,7 @@ pub fn recv_data<CI, CO, DO>(
|
|||||||
data_out: &mut DO,
|
data_out: &mut DO,
|
||||||
) -> io::Result<bool>
|
) -> io::Result<bool>
|
||||||
where
|
where
|
||||||
CI: io::Read,
|
CI: io::BufRead,
|
||||||
CO: io::Write,
|
CO: io::Write,
|
||||||
DO: io::Write,
|
DO: io::Write,
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ pub fn recv<CI, CO, DO>(
|
|||||||
mut data_out: DO,
|
mut data_out: DO,
|
||||||
) -> io::Result<usize>
|
) -> io::Result<usize>
|
||||||
where
|
where
|
||||||
CI: io::Read,
|
CI: io::BufRead,
|
||||||
CO: io::Write,
|
CO: io::Write,
|
||||||
DO: io::Write,
|
DO: io::Write,
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user