use thiserror::Error;
use crate::{decompress::{DecompressionError, Decompressor}, decrypt::{DecryptionError, Decryptor}};
#[derive(Debug, Error)]
pub enum PipelineError {
#[error("decryption error: {0}")]
Decryption(#[from] DecryptionError),
#[error("decompression error: {0}")]
Decompression(#[from] DecompressionError)
}
#[derive(Debug)]
pub struct Pipeline {
decryptor: Option<Box<dyn Decryptor>>,
decompressor: Option<Box<dyn Decompressor>>,
decrypt_buffer: Vec<u8>,
result_buffer: Vec<u8>
}
impl Pipeline {
pub fn new(decryptor: Option<Box<dyn Decryptor>>, decompressor: Option<Box<dyn Decompressor>>) -> Self {
Self {
decryptor,
decompressor,
decrypt_buffer: Vec::new(),
result_buffer: Vec::new()
}
}
pub fn update(&mut self, data: &[u8]) -> Result<(usize, &[u8]), PipelineError> {
if self.decryptor.is_some() && self.decompressor.is_some() {
let decryptor = self.decryptor.as_deref_mut().unwrap();
let decompressor = self.decompressor.as_deref_mut().unwrap();
let (dcr_count, dcr_data) = decryptor.update(data)?;
self.decrypt_buffer.extend(dcr_data);
self.result_buffer.clear();
let decrypt_slice = self.decrypt_buffer.as_slice();
let mut offset = 0;
loop {
let (dcm_count, dcm_data) = decompressor.update(&decrypt_slice[offset..])?;
self.result_buffer.extend(dcm_data);
if dcm_count == 0 {
break;
}
offset += dcm_count;
}
self.decrypt_buffer.drain(0..offset);
Ok((dcr_count, &self.result_buffer))
} else if let Some(decryptor) = self.decryptor.as_deref_mut() {
Ok(decryptor.update(data)?)
} else if let Some(decompressor) = self.decompressor.as_deref_mut() {
Ok(decompressor.update(data)?)
} else {
self.result_buffer = Vec::from(data);
Ok((data.len(), &self.result_buffer))
}
}
}