flute 1.11.0

File Delivery over Unidirectional Transport (FLUTE)
Documentation
use crate::common::{
    alc,
    oti::{self, SchemeSpecific},
};
use crate::error::FluteError;
use crate::fec;
use crate::fec::nocode;
use crate::fec::rscodec;
use crate::fec::FecDecoder;
use crate::tools::error::Result;

#[derive(Debug)]
pub struct BlockDecoder {
    pub completed: bool,
    pub initialized: bool,
    pub block_size: usize,
    decoder: Option<Box<dyn FecDecoder>>,
}

impl BlockDecoder {
    pub fn new() -> BlockDecoder {
        BlockDecoder {
            completed: false,
            initialized: false,
            decoder: None,
            block_size: 0,
        }
    }

    pub fn init(
        &mut self,
        oti: &oti::Oti,
        nb_source_symbols: u32,
        block_size: usize,
        sbn: u32,
    ) -> Result<()> {
        if self.initialized {
            return Ok(());
        }

        match oti.fec_encoding_id {
            oti::FECEncodingID::NoCode => {
                let codec = nocode::NoCodeDecoder::new(nb_source_symbols as usize);
                self.decoder = Some(Box::new(codec));
            }
            oti::FECEncodingID::ReedSolomonGF28 => {
                let codec = rscodec::RSGalois8Codec::new(
                    nb_source_symbols as usize,
                    oti.max_number_of_parity_symbols as usize,
                    oti.encoding_symbol_length as usize,
                )?;
                self.decoder = Some(Box::new(codec));
            }
            oti::FECEncodingID::ReedSolomonGF28UnderSpecified => {
                let codec = rscodec::RSGalois8Codec::new(
                    nb_source_symbols as usize,
                    oti.max_number_of_parity_symbols as usize,
                    oti.encoding_symbol_length as usize,
                )?;
                self.decoder = Some(Box::new(codec));
            }
            oti::FECEncodingID::ReedSolomonGF2M => {
                log::warn!("Not implemented")
            }
            oti::FECEncodingID::RaptorQ => {
                if let Some(SchemeSpecific::RaptorQ(scheme)) = oti.scheme_specific.as_ref() {
                    let codec = fec::raptorq::RaptorQDecoder::new(
                        sbn,
                        nb_source_symbols as usize,
                        oti.encoding_symbol_length as usize,
                        scheme,
                    );
                    self.decoder = Some(Box::new(codec));
                } else {
                    return Err(FluteError::new("RaptorQ Scheme not found"));
                }
            }
            oti::FECEncodingID::Raptor => {
                if oti.scheme_specific.is_none() {
                    return Err(FluteError::new("Raptor Scheme not found"));
                }

                let codec = fec::raptor::RaptorDecoder::new(nb_source_symbols as usize, block_size);
                self.decoder = Some(Box::new(codec));
            }
        }

        self.initialized = true;
        self.block_size = block_size;
        Ok(())
    }

    pub fn source_block(&self) -> Result<&[u8]> {
        if self.decoder.is_none() {
            return Err(FluteError::new("Fail to decode block"));
        }

        self.decoder.as_ref().unwrap().source_block()
    }

    pub fn deallocate(&mut self) {
        self.decoder = None;
        self.block_size = 0;
    }

    pub fn push(&mut self, pkt: &alc::AlcPkt, payload_id: &alc::PayloadID) {
        debug_assert!(self.initialized);

        if self.completed {
            return;
        }

        debug_assert!(self.decoder.is_some());
        if self.decoder.is_none() {
            log::error!("Decoder has been deallocated");
            return;
        }

        let payload = &pkt.data[pkt.data_payload_offset..];
        let decoder = self.decoder.as_mut().unwrap();
        decoder.push_symbol(payload, payload_id.esi);

        if decoder.can_decode() {
            self.completed = decoder.decode();
            if self.completed {
                log::debug!("Block completed");
            }
        }
    }
}