use crate::{Config, Error, FrameSizes, FrameSpec, Metadata, Result};
use crate::{compression::CompressionState, crypto::EncryptionState};
pub struct Encoder {
config: Config,
compression: CompressionState,
encryption: EncryptionState,
}
impl TryFrom<&Metadata> for Encoder {
type Error = Error;
fn try_from(metadata: &Metadata) -> Result<Self> {
let config = metadata.config().clone();
Ok(Self {
compression: CompressionState::new(config.compression())?,
encryption: EncryptionState::new(config.encryption())?,
config,
})
}
}
impl TryFrom<Metadata> for Encoder {
type Error = Error;
fn try_from(metadata: Metadata) -> Result<Self> {
Self::try_from(&metadata)
}
}
impl Encoder {
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
}
pub fn encode_frame_alloc(
&mut self,
index: u64,
buffer: &[u8],
) -> Result<(Vec<u8>, FrameSizes)> {
let capacity = buffer
.len()
.checked_add(self.encryption.overhead())
.ok_or(Error::Overflow)?;
let mut encoded = Vec::new();
encoded
.try_reserve(capacity)
.map_err(|_| Error::Allocation)?;
encoded.extend_from_slice(buffer);
let sizes = self.encode_frame(index, &mut encoded)?;
Ok((encoded, sizes))
}
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 {
config: Config,
compression: CompressionState,
encryption: EncryptionState,
}
impl TryFrom<&Metadata> for Decoder {
type Error = Error;
fn try_from(metadata: &Metadata) -> Result<Self> {
let config = metadata.config().clone();
Ok(Self {
compression: CompressionState::new(config.compression())?,
encryption: EncryptionState::new(config.encryption())?,
config,
})
}
}
impl TryFrom<Metadata> for Decoder {
type Error = Error;
fn try_from(metadata: Metadata) -> Result<Self> {
Self::try_from(&metadata)
}
}
impl Decoder {
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(())
}
}