mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-06-19 11:02:06 +00:00
Merge "Ports zmodem to no_std and kata_io"
GitOrigin-RevId: 09bc871f7c4fdd64f3b4591a47cf5ba0bffa72c2
This commit is contained in:
parent
c0a44de935
commit
66c03e7858
@ -7,6 +7,7 @@ members = [
|
|||||||
"kata-logger",
|
"kata-logger",
|
||||||
"kata-shell",
|
"kata-shell",
|
||||||
"kata-uart-client",
|
"kata-uart-client",
|
||||||
|
"zmodem",
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
use core::cmp;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
@ -31,6 +34,8 @@ pub trait Read {
|
|||||||
pub trait Write {
|
pub trait Write {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
||||||
|
|
||||||
|
fn flush(&mut self) -> Result<()>;
|
||||||
|
|
||||||
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
|
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
|
||||||
while !buf.is_empty() {
|
while !buf.is_empty() {
|
||||||
match self.write(buf) {
|
match self.write(buf) {
|
||||||
@ -64,3 +69,37 @@ pub enum SeekFrom {
|
|||||||
pub trait Seek {
|
pub trait Seek {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
|
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Read for &[u8] {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
let amt = cmp::min(buf.len(), self.len());
|
||||||
|
let (a, b) = self.split_at(amt);
|
||||||
|
buf[..amt].copy_from_slice(a);
|
||||||
|
*self = b;
|
||||||
|
Ok(amt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwarding implementation of Read for &mut
|
||||||
|
impl<'a, T> 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> 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ pub extern "C" fn logger_log(level: u8, msg: *const cstr_core::c_char) {
|
|||||||
pub struct Rx {}
|
pub struct Rx {}
|
||||||
|
|
||||||
impl io::Read for Rx {
|
impl io::Read for Rx {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
unsafe {
|
unsafe {
|
||||||
rx_mutex_lock();
|
rx_mutex_lock();
|
||||||
uart_rx_update(buf.len());
|
uart_rx_update(buf.len());
|
||||||
@ -55,7 +55,7 @@ impl io::Read for Rx {
|
|||||||
pub struct Tx {}
|
pub struct Tx {}
|
||||||
|
|
||||||
impl io::Write for Tx {
|
impl io::Write for Tx {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
unsafe {
|
unsafe {
|
||||||
tx_mutex_lock();
|
tx_mutex_lock();
|
||||||
let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
|
let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
|
||||||
@ -65,4 +65,9 @@ impl io::Write for Tx {
|
|||||||
}
|
}
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
// Do nothing. This implementation has no internal buffering.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,12 @@ license = "MIT OR Apache-2.0"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.21.1"
|
crc = { version = "1.4.0", default_features = false }
|
||||||
crc = "1.4.0"
|
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
|
||||||
env_logger = "0.4.2"
|
kata-io = { path = "../kata-io" }
|
||||||
hex = "0.2.0"
|
log = { version = "0.4.14", default-features = false }
|
||||||
hexdump = "0.1.0"
|
|
||||||
log = "0.3.7"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1"
|
env_logger = "0.9.0"
|
||||||
|
lazy_static = { version = "1.4.0", features = ["spin"] }
|
||||||
rand = "0.3.15"
|
rand = "0.3.15"
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
extern crate zmodem;
|
|
||||||
|
|
||||||
extern crate clap;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
mod stdinout;
|
|
||||||
|
|
||||||
use clap::{App, Arg};
|
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
env_logger::init().unwrap();
|
|
||||||
|
|
||||||
let matches = App::new("Pure Rust implementation of rz utility")
|
|
||||||
.arg(Arg::with_name("file").required(false).index(1))
|
|
||||||
.get_matches();
|
|
||||||
|
|
||||||
let fileopt = matches.value_of("file").unwrap_or("rz-out");
|
|
||||||
let filename = Path::new(fileopt).file_name().unwrap().clone();
|
|
||||||
let file = File::create(filename).expect(&format!("Cannot create file {:?}:", filename));
|
|
||||||
|
|
||||||
let inout = stdinout::CombinedStdInOut::new();
|
|
||||||
zmodem::recv::recv(inout, file).unwrap();
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
use std::io::*;
|
|
||||||
|
|
||||||
pub struct CombinedStdInOut {
|
|
||||||
stdin: Stdin,
|
|
||||||
stdout: Stdout,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CombinedStdInOut {
|
|
||||||
pub fn new() -> CombinedStdInOut {
|
|
||||||
CombinedStdInOut {
|
|
||||||
stdin: stdin(),
|
|
||||||
stdout: stdout(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Read for CombinedStdInOut {
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
|
||||||
self.stdin.read(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for CombinedStdInOut {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
|
||||||
let r = self.stdout.write(buf)?;
|
|
||||||
self.stdout.flush()?;
|
|
||||||
Ok(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> Result<()> {
|
|
||||||
self.stdout.flush()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
extern crate zmodem;
|
|
||||||
|
|
||||||
extern crate clap;
|
|
||||||
extern crate env_logger;
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
mod stdinout;
|
|
||||||
|
|
||||||
use clap::{App, Arg};
|
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
env_logger::init().unwrap();
|
|
||||||
|
|
||||||
let matches = App::new("Pure Rust implementation of sz utility")
|
|
||||||
.arg(Arg::with_name("file").required(true).index(1))
|
|
||||||
.get_matches();
|
|
||||||
|
|
||||||
let fileopt = matches.value_of("file").unwrap();
|
|
||||||
let mut file = File::open(fileopt).unwrap();
|
|
||||||
|
|
||||||
let filename = Path::new(fileopt).file_name().unwrap().clone();
|
|
||||||
let size = file.metadata().map(|x| x.len() as u32).ok();
|
|
||||||
|
|
||||||
let inout = stdinout::CombinedStdInOut::new();
|
|
||||||
|
|
||||||
zmodem::send::send(inout, &mut file, filename.to_str().unwrap(), size).unwrap();
|
|
||||||
}
|
|
@ -1,8 +1,11 @@
|
|||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
use consts::*;
|
use consts::*;
|
||||||
use crc;
|
use crc;
|
||||||
use hex::*;
|
use hex::*;
|
||||||
use proto;
|
use proto;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
@ -59,7 +62,7 @@ impl Frame {
|
|||||||
out.append(&mut crc);
|
out.append(&mut crc);
|
||||||
|
|
||||||
if self.header == ZHEX {
|
if self.header == ZHEX {
|
||||||
let hex = out.drain(4..).collect::<Vec<u8>>().to_hex();
|
let hex = out.drain(4..).collect::<Vec<u8>>().encode_hex::<String>();
|
||||||
out.extend_from_slice(&hex.as_bytes());
|
out.extend_from_slice(&hex.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +98,8 @@ fn get_crc(header: u8, buf: &[u8]) -> Vec<u8> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match header {
|
match header {
|
||||||
ZBIN32 => crc::get_crc32(&buf[offset..], None).to_vec(),
|
ZBIN32 => crc::get_crc32(&buf[offset..], None).into(),
|
||||||
_ => crc::get_crc16(&buf[offset..], None).to_vec(),
|
_ => crc::get_crc16(&buf[offset..], None).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +142,8 @@ impl fmt::Display for Frame {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_frame() {
|
fn test_frame() {
|
||||||
|
use alloc::vec;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Frame::new(ZBIN, 0).build(),
|
Frame::new(ZBIN, 0).build(),
|
||||||
vec![ZPAD, ZLDE, ZBIN, 0, 0, 0, 0, 0, 0, 0]
|
vec![ZPAD, ZLDE, ZBIN, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#[macro_use]
|
#![no_std]
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
extern crate crc as crc32;
|
extern crate crc as crc32;
|
||||||
extern crate hex;
|
extern crate hex;
|
||||||
extern crate hexdump;
|
extern crate kata_io;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
mod consts;
|
mod consts;
|
||||||
mod crc;
|
mod crc;
|
||||||
mod frame;
|
mod frame;
|
||||||
mod proto;
|
mod proto;
|
||||||
mod rwlog;
|
|
||||||
|
|
||||||
pub mod recv;
|
pub mod recv;
|
||||||
pub mod send;
|
pub mod send;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use hex::*;
|
use alloc::vec::Vec;
|
||||||
use log::LogLevel::Debug;
|
use alloc::{format, vec};
|
||||||
use std::io;
|
|
||||||
|
use kata_io as io;
|
||||||
|
use log::Level::Debug;
|
||||||
|
|
||||||
use consts::*;
|
use consts::*;
|
||||||
use crc::*;
|
use crc::*;
|
||||||
@ -55,7 +57,7 @@ where
|
|||||||
read_exact_unescaped(r, &mut v)?;
|
read_exact_unescaped(r, &mut v)?;
|
||||||
|
|
||||||
if header == ZHEX {
|
if header == ZHEX {
|
||||||
v = match FromHex::from_hex(&v) {
|
v = match hex::decode(&v) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
_ => {
|
_ => {
|
||||||
error!("from_hex error");
|
error!("from_hex error");
|
||||||
@ -104,15 +106,37 @@ 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::BufRead,
|
R: io::Read,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
r.read_until(ZLDE, buf)?;
|
read_until(r, ZLDE, buf)?;
|
||||||
let b = read_byte(r)?;
|
let b = read_byte(r)?;
|
||||||
|
|
||||||
if !is_escaped(b) {
|
if !is_escaped(b) {
|
||||||
@ -148,7 +172,7 @@ pub fn recv_data<RW, OUT>(
|
|||||||
out: &mut OUT,
|
out: &mut OUT,
|
||||||
) -> io::Result<bool>
|
) -> io::Result<bool>
|
||||||
where
|
where
|
||||||
RW: io::Write + io::BufRead,
|
RW: io::Write + io::Read,
|
||||||
OUT: io::Write,
|
OUT: io::Write,
|
||||||
{
|
{
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
@ -182,7 +206,8 @@ where
|
|||||||
debug!("CCRCG: CRC next, frame continues nonstop");
|
debug!("CCRCG: CRC next, frame continues nonstop");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!(format!("unexpected ZCRC byte: {:02X}", zcrc));
|
error!("unexpected ZCRC byte: {:02X}", zcrc);
|
||||||
|
return Err(io::Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use std::io::{Read, Result, Write};
|
use alloc::vec::Vec;
|
||||||
use std::str::from_utf8;
|
use core::str::from_utf8;
|
||||||
use std::{thread, time};
|
|
||||||
|
use kata_io as io;
|
||||||
|
|
||||||
use consts::*;
|
use consts::*;
|
||||||
use frame::*;
|
use frame::*;
|
||||||
use proto::*;
|
use proto::*;
|
||||||
use rwlog;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum State {
|
enum State {
|
||||||
@ -53,12 +53,13 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Receives data by Z-Modem protocol
|
/// Receives data by Z-Modem protocol
|
||||||
pub fn recv<RW, W>(rw: RW, mut w: W) -> Result<usize>
|
pub fn recv<RW, W>(rw: RW, mut w: W) -> io::Result<usize>
|
||||||
where
|
where
|
||||||
RW: Read + Write,
|
RW: io::Read + io::Write,
|
||||||
W: Write,
|
W: io::Write,
|
||||||
{
|
{
|
||||||
let mut rw_log = rwlog::ReadWriteLog::new(rw);
|
let mut rw_log = rw;
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
@ -121,7 +122,11 @@ where
|
|||||||
}
|
}
|
||||||
State::Done => {
|
State::Done => {
|
||||||
write_zfin(&mut rw_log)?;
|
write_zfin(&mut rw_log)?;
|
||||||
thread::sleep(time::Duration::from_millis(10)); // sleep a bit
|
// NB: lexxvir/zmodem had a 10ms sleep here that has been removed
|
||||||
|
// due to no_std. Here we change it to flush() so that a return
|
||||||
|
// from this function does really indicate all the bytes have
|
||||||
|
// been written.
|
||||||
|
rw_log.flush()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,9 +134,9 @@ where
|
|||||||
Ok(count as usize)
|
Ok(count as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv_error<W>(w: &mut W, state: &State, count: u32) -> Result<()>
|
fn recv_error<W>(w: &mut W, state: &State, count: u32) -> io::Result<()>
|
||||||
where
|
where
|
||||||
W: Write,
|
W: io::Write,
|
||||||
{
|
{
|
||||||
// TODO: flush input
|
// TODO: flush input
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use std::io::{Read, Result, Seek, SeekFrom, Write};
|
use kata_io as io;
|
||||||
|
|
||||||
use consts::*;
|
use consts::*;
|
||||||
use frame::*;
|
use frame::*;
|
||||||
use proto::*;
|
use proto::*;
|
||||||
use rwlog;
|
|
||||||
|
|
||||||
const SUBPACKET_SIZE: usize = 1024 * 8;
|
const SUBPACKET_SIZE: usize = 1024 * 8;
|
||||||
const SUBPACKET_PER_ACK: usize = 10;
|
const SUBPACKET_PER_ACK: usize = 10;
|
||||||
@ -63,12 +62,12 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send<RW, R>(rw: RW, r: &mut R, filename: &str, filesize: Option<u32>) -> Result<()>
|
pub fn send<RW, R>(rw: RW, r: &mut R, filename: &str, filesize: Option<u32>) -> io::Result<()>
|
||||||
where
|
where
|
||||||
RW: Read + Write,
|
RW: io::Read + io::Write,
|
||||||
R: Read + Seek,
|
R: io::Read + io::Seek,
|
||||||
{
|
{
|
||||||
let mut rw_log = rwlog::ReadWriteLog::new(rw);
|
let mut rw_log = rw;
|
||||||
|
|
||||||
let mut data = [0; SUBPACKET_SIZE];
|
let mut data = [0; SUBPACKET_SIZE];
|
||||||
let mut offset: u32;
|
let mut offset: u32;
|
||||||
@ -105,7 +104,7 @@ where
|
|||||||
}
|
}
|
||||||
State::SendingData => {
|
State::SendingData => {
|
||||||
offset = frame.get_count();
|
offset = frame.get_count();
|
||||||
r.seek(SeekFrom::Start(offset as u64))?;
|
r.seek(io::SeekFrom::Start(offset as u64))?;
|
||||||
|
|
||||||
let num = r.read(&mut data)?;
|
let num = r.read(&mut data)?;
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@ use std::result;
|
|||||||
use std::thread::{sleep, spawn};
|
use std::thread::{sleep, spawn};
|
||||||
use std::time::*;
|
use std::time::*;
|
||||||
|
|
||||||
|
extern crate kata_io;
|
||||||
|
|
||||||
|
fn forget_err(_e: std::io::Error) -> kata_io::Error {
|
||||||
|
kata_io::Error {}
|
||||||
|
}
|
||||||
|
|
||||||
struct InOut<R: Read, W: Write> {
|
struct InOut<R: Read, W: Write> {
|
||||||
r: R,
|
r: R,
|
||||||
w: W,
|
w: W,
|
||||||
@ -23,24 +29,66 @@ impl<R: Read, W: Write> InOut<R, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read, W: Write> Read for InOut<R, W> {
|
impl<R: Read, W: Write> kata_io::Read for InOut<R, W> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> kata_io::Result<usize> {
|
||||||
self.r.read(buf)
|
self.r.read(buf).map_err(forget_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read, W: Write> Write for InOut<R, W> {
|
impl<R: Read, W: Write> kata_io::Write for InOut<R, W> {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> kata_io::Result<usize> {
|
||||||
self.w.write(buf)
|
self.w.write(buf).map_err(forget_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> Result<()> {
|
fn flush(&mut self) -> kata_io::Result<()> {
|
||||||
self.w.flush()
|
self.w.flush().map_err(forget_err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Minimal vector-backed kata_io::Read and kata_io::Write
|
||||||
|
///
|
||||||
|
/// This is a workaround to not being able to implement the kata_io traits for
|
||||||
|
/// std::io::Cursor in this file, since none of those come from the current
|
||||||
|
/// crate.
|
||||||
|
struct WrappedCursor<T> {
|
||||||
|
c: std::io::Cursor<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WrappedCursor<T> {
|
||||||
|
pub fn into_inner(self) -> T {
|
||||||
|
self.c.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl kata_io::Read for WrappedCursor<&Vec<u8>> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> kata_io::Result<usize> {
|
||||||
|
self.c.read(buf).map_err(forget_err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl kata_io::Write for WrappedCursor<Vec<u8>> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> kata_io::Result<usize> {
|
||||||
|
self.c.write(buf).map_err(forget_err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> kata_io::Result<()> {
|
||||||
|
self.c.flush().map_err(forget_err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl kata_io::Seek for WrappedCursor<&Vec<u8>> {
|
||||||
|
fn seek(&mut self, pos: kata_io::SeekFrom) -> kata_io::Result<u64> {
|
||||||
|
let std_pos = match pos {
|
||||||
|
kata_io::SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
|
||||||
|
kata_io::SeekFrom::End(n) => std::io::SeekFrom::End(n),
|
||||||
|
kata_io::SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
|
||||||
|
};
|
||||||
|
self.c.seek(std_pos).map_err(forget_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref LOG_INIT: result::Result<(), log::SetLoggerError> = env_logger::init();
|
static ref LOG_INIT: result::Result<(), log::SetLoggerError> = Ok(env_logger::init());
|
||||||
static ref RND_VALUES: Vec<u8> = {
|
static ref RND_VALUES: Vec<u8> = {
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
@ -69,7 +117,9 @@ fn recv_from_sz() {
|
|||||||
let child_stdout = sz.stdout.unwrap();
|
let child_stdout = sz.stdout.unwrap();
|
||||||
let mut inout = InOut::new(child_stdout, child_stdin);
|
let mut inout = InOut::new(child_stdout, child_stdin);
|
||||||
|
|
||||||
let mut c = Cursor::new(Vec::new());
|
let mut c = WrappedCursor {
|
||||||
|
c: Cursor::new(Vec::new()),
|
||||||
|
};
|
||||||
zmodem::recv::recv(&mut inout, &mut c).unwrap();
|
zmodem::recv::recv(&mut inout, &mut c).unwrap();
|
||||||
|
|
||||||
sleep(Duration::from_millis(300));
|
sleep(Duration::from_millis(300));
|
||||||
@ -97,7 +147,9 @@ fn send_to_rz() {
|
|||||||
|
|
||||||
let len = RND_VALUES.len() as u32;
|
let len = RND_VALUES.len() as u32;
|
||||||
let copy = RND_VALUES.clone();
|
let copy = RND_VALUES.clone();
|
||||||
let mut cur = Cursor::new(©);
|
let mut cur = WrappedCursor {
|
||||||
|
c: Cursor::new(©),
|
||||||
|
};
|
||||||
|
|
||||||
sleep(Duration::from_millis(300));
|
sleep(Duration::from_millis(300));
|
||||||
|
|
||||||
@ -141,12 +193,16 @@ fn lib_send_recv() {
|
|||||||
let mut inout = InOut::new(inf, outf);
|
let mut inout = InOut::new(inf, outf);
|
||||||
|
|
||||||
let origin = RND_VALUES.clone();
|
let origin = RND_VALUES.clone();
|
||||||
let mut c = Cursor::new(&origin);
|
let mut c = WrappedCursor {
|
||||||
|
c: Cursor::new(&origin),
|
||||||
|
};
|
||||||
|
|
||||||
zmodem::send::send(&mut inout, &mut c, "test", None).unwrap();
|
zmodem::send::send(&mut inout, &mut c, "test", None).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut c = Cursor::new(Vec::new());
|
let mut c = WrappedCursor {
|
||||||
|
c: Cursor::new(Vec::new()),
|
||||||
|
};
|
||||||
|
|
||||||
let inf = File::open("test-fifo1").unwrap();
|
let inf = File::open("test-fifo1").unwrap();
|
||||||
let outf = OpenOptions::new().write(true).open("test-fifo2").unwrap();
|
let outf = OpenOptions::new().write(true).open("test-fifo2").unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user