ptero/
decoder.rs

1use std::{convert::TryFrom, error::Error, sync::mpsc::Sender};
2
3use log::{debug};
4
5use crate::{binary::{Bit, BitVec}, cli::progress::ProgressStatus, context::{Context, ContextError}};
6
7// TODO: Provide DecoderError and mapping from ContextError
8/// Base trait for all data decoders.
9/// The generic type should contain data need by the decoder implementation.
10pub trait Decoder<D> where D: Context {
11    /// Decodes bits from the cover text.
12    /// The access to the cover text is bound by the [Context].
13    ///
14    /// # Arguments
15    ///
16    /// * `context` - context of the steganography method, can contain various needed info like pivot etc.
17    ///
18    /// # Returns
19    /// It returns `Result`, either decoded data as as vector of [Bits] or error.
20    ///
21    /// [Context]: crate::context::Context
22    /// [Bits]: crate::binary::Bit
23    fn partial_decode(&self, context: &D) -> Result<Vec<Bit>, ContextError>;
24
25    fn decode(&self, context: &mut D, progress_channel: Option<&Sender<ProgressStatus>>) -> Result<Vec<u8>, Box<dyn Error>> {
26        let mut secret = Vec::default();
27        debug!("Decoding secret from the text");
28        while context.load_text().is_ok() {
29            let mut data = self.partial_decode(&context)?;
30            if let Some(tx) = progress_channel {
31                tx.send(ProgressStatus::Step(context.get_current_text()?.len() as u64)).ok();
32            }
33            secret.append(&mut data);
34        }
35        debug!("Padding bits to byte size boundary");
36        while &secret.len() % 8 != 0 {
37            secret.push(Bit(0));
38        }
39    
40        debug!("Converting bits to bytes");
41        let bit_vec: BitVec = secret.into();
42        let bytes: Vec<u8> = TryFrom::try_from(bit_vec)?;
43        Ok(bytes)
44    }
45}