#![allow(dead_code)]
extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String;
use anyhow::Result;
use core2::io::{Error, Read, Write};
use thiserror_no_std::Error;
pub use utils::*;
#[derive(Default, Copy, Clone, Debug)]
pub enum ChecksumKind {
#[default]
Standard,
Crc16,
}
#[derive(Default, Copy, Clone, Debug)]
pub enum BlockLengthKind {
#[default]
Standard = 128,
OneK = 1024,
}
#[derive(Debug, Error)]
pub enum ModemError {
#[error("Error during I/O on the channel.")]
Io(#[from] Error),
#[error("Too many errors, aborting - max errors: {errors}")]
ExhaustedRetries { errors: Box<u32> },
#[error("Cancelled by the other party.")]
Canceled,
}
pub type ModemResult<T, E = ModemError> = Result<T, E>;
mod utils {
use super::Read;
use core2::io::{ErrorKind, Result};
pub fn calc_checksum(data: &[u8]) -> u8 {
data.iter().fold(0, |x, &y| x.wrapping_add(y))
}
pub fn calc_crc(data: &[u8]) -> u16 {
crc16::State::<crc16::XMODEM>::calculate(data)
}
pub fn get_byte<R: Read>(reader: &mut R) -> Result<u8> {
let mut buff = [0];
reader.read_exact(&mut buff)?;
Ok(buff[0])
}
pub fn get_byte_timeout<R: Read>(reader: &mut R) -> Result<Option<u8>> {
match get_byte(reader) {
Ok(c) => Ok(Some(c)),
Err(err) => {
if err.kind() == ErrorKind::TimedOut {
Ok(None)
} else {
Err(err)
}
}
}
}
}
pub trait ModemTrait {
fn new() -> Self
where
Self: Sized;
}
pub trait XModemTrait: ModemTrait {
fn send<D: Read + Write, R: Read>(
&mut self,
dev: &mut D,
inp: &mut R,
) -> ModemResult<()>;
fn receive<D: Read + Write, W: Write>(
&mut self,
dev: &mut D,
out: &mut W,
checksum: ChecksumKind,
) -> ModemResult<()>;
fn init_send<D: Read + Write>(&mut self, dev: &mut D) -> ModemResult<()>;
fn finish_send<D: Read + Write>(&mut self, dev: &mut D) -> ModemResult<()>;
fn send_stream<D: Read + Write, R: Read>(
&mut self,
dev: &mut D,
inp: &mut R,
) -> ModemResult<()>;
}
#[allow(dead_code)] pub trait YModemTrait: ModemTrait {
fn recv<D: Read + Write, W: Write>(
&mut self,
dev: &mut D,
out: &mut W,
file_name: &mut String,
file_size: &mut u32,
) -> ModemResult<()>;
fn send<D: Read + Write, R: Read>(
&mut self,
dev: &mut D,
inp: &mut R,
file_name: String,
file_size: u64,
) -> ModemResult<()>;
fn send_stream<D: Read + Write, R: Read>(
&mut self,
dev: &mut D,
stream: &mut R,
packets_to_send: u32,
last_packet_size: u64,
) -> ModemResult<()>;
fn send_start_frame<D: Read + Write>(
&mut self,
dev: &mut D,
file_name: String,
file_size: u64,
) -> ModemResult<()>;
fn send_end_frame<D: Read + Write>(
&mut self,
dev: &mut D,
) -> ModemResult<()>;
}