#![cfg_attr(not(feature = "std"), no_std)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
extern crate alloc;
use alloc::{vec, vec::Vec};
use core::fmt;
pub mod escape;
pub use escape::{OnePassEscapeEngine, ShellDecodeMode, TrSedEngine, TwoPassEscapeEngine, TR_SED};
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum EscnulError {
#[error("Buffer too small")]
BufferTooSmall(Progress),
#[error("Truncated input")]
TruncatedInput(Progress),
#[error("Bad escape byte: {0:#04x}")]
BadEscapes(u8),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Progress {
pub processed: usize,
pub written: usize,
}
impl fmt::Display for Progress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "processed={}, written={}", self.processed, self.written)
}
}
pub trait Encode {
fn encode_slice<T: AsRef<[u8]>>(
&self,
input: T,
output: &mut [u8],
) -> Result<usize, EscnulError>;
fn encode<T: AsRef<[u8]>>(&self, input: T) -> Vec<u8> {
let mut output = vec![0; input.as_ref().len() * 2];
let n = self.encode_slice(input, &mut output).unwrap();
output.truncate(n);
output
}
}
pub trait Decode {
fn decode_slice<T: AsRef<[u8]>>(
&self,
input: T,
output: &mut [u8],
) -> Result<usize, EscnulError>;
fn decode<T: AsRef<[u8]>>(&self, input: T) -> Vec<u8> {
let mut output = vec![0; input.as_ref().len()];
let n = self.decode_slice(input, &mut output).unwrap();
output.truncate(n);
output
}
}
pub trait Engine: Encode + Decode {}
#[cfg(feature = "std")]
#[derive(Debug, thiserror::Error)]
pub enum StreamEncodeError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Escnul(#[from] EscnulError),
}