use crate::{
CompressionCodec, Config, EncryptionCodec, Error, FrameSizes, FrameSpec, Framing, Result,
};
#[derive(Clone, Copy, Debug, Default)]
pub struct Identity;
impl crate::sealed::Sealed for Identity {}
pub struct Encoder<C = Identity, E = Identity> {
config: Config,
compression: C,
encryption: E,
}
impl<C: CompressionCodec, E: EncryptionCodec> Encoder<C, E> {
pub fn new(framing: Framing, compression: C, encryption: E) -> Result<Self> {
let config = Config::new(framing, C::FORMAT, E::FORMAT)?;
Ok(Self {
config,
compression,
encryption,
})
}
pub fn config(&self) -> Config {
self.config
}
pub fn encode_frame(&mut self, index: u64, buffer: &mut Vec<u8>) -> Result<FrameSizes> {
let result = self.encode_inner(index, buffer);
if result.is_err() {
buffer.clear();
}
result
}
fn encode_inner(&mut self, index: u64, buffer: &mut Vec<u8>) -> Result<FrameSizes> {
let raw = buffer.len() as u64;
self.config.validate_frame(index, raw, raw)?;
self.compression.encode(buffer)?;
let payload = buffer.len() as u64;
self.encryption.seal(index, buffer)?;
Ok(FrameSizes { raw, payload })
}
}
pub struct Decoder<C = Identity, E = Identity> {
config: Config,
compression: C,
encryption: E,
}
impl<C: CompressionCodec, E: EncryptionCodec> Decoder<C, E> {
pub fn new(config: Config, compression: C, encryption: E) -> Result<Self> {
if config.compression() != C::FORMAT || config.encryption() != E::FORMAT {
return Err(Error::ProfileMismatch);
}
Ok(Self {
config,
compression,
encryption,
})
}
pub fn decode_frame(&mut self, spec: FrameSpec, buffer: &mut Vec<u8>) -> Result<()> {
let result = self.decode_inner(spec, buffer);
if result.is_err() {
buffer.clear();
}
result
}
fn decode_inner(&mut self, spec: FrameSpec, buffer: &mut Vec<u8>) -> Result<()> {
if spec.config != self.config {
return Err(Error::ProfileMismatch);
}
if buffer.len() != spec.stored_len() {
return Err(Error::InvalidStoredLength);
}
self.encryption.open(spec.index(), buffer)?;
if spec.payload_len() < spec.raw_len() {
self.compression.decode(buffer, spec.raw_len())?;
}
if buffer.len() != spec.raw_len() {
return Err(Error::DecompressionFailed);
}
Ok(())
}
}