zstd-complete 0.3.0

A pure Rust Zstandard compressor and decompressor with bounded streaming I/O
Documentation
use alloc::vec::Vec;

use crate::{bit_io::BitWriter, blocks::sequence_section::Sequence, fse::fse_encoder::FSETable};

use super::encode_sequences;

mod builder;
mod selection;

pub(in crate::encoding::blocks::compressed) use builder::{build_sequence_table, TableBuilder};
#[cfg(test)]
pub(super) use selection::choose_table;
pub(super) use selection::{
    choose_c_dfast_compact_sequence_table_modes_from_prepared,
    choose_c_dfast_compact_sequence_table_modes_from_stored,
    choose_c_dfast_compact_sequence_table_modes_from_stored_with_final_history,
    choose_c_fast_sequence_table_modes_from_prepared,
    choose_c_fast_sequence_table_modes_from_stored,
    choose_c_fast_sequence_table_modes_from_stored_with_final_history,
    choose_c_sequence_table_modes_from_prepared, choose_c_sequence_table_modes_from_stored,
    choose_c_sequence_table_modes_from_stored_with_scratch, choose_sequence_table_modes,
    choose_sequence_table_modes_for_estimate,
    choose_sequence_table_modes_for_estimate_from_counts_with_scratch,
};

#[derive(Clone)]
#[allow(clippy::large_enum_variant)]
pub(super) enum FseTableMode<'a> {
    Predefined(&'a FSETable),
    Rle(u8),
    Encoded(FSETable),
    RepeatLast(&'a FSETable),
}

impl FseTableMode<'_> {
    pub(super) fn table(&self) -> Option<&FSETable> {
        match self {
            Self::Predefined(t) => Some(t),
            Self::RepeatLast(t) => Some(t),
            Self::Encoded(t) => Some(t),
            Self::Rle(_) => None,
        }
    }
}

pub(super) struct SequenceModeSearchConfig<'a> {
    pub(super) ll_previous: Option<&'a FSETable>,
    pub(super) ll_repeat_valid: bool,
    pub(super) ll_default: &'a FSETable,
    pub(super) ml_previous: Option<&'a FSETable>,
    pub(super) ml_repeat_valid: bool,
    pub(super) ml_default: &'a FSETable,
    pub(super) of_previous: Option<&'a FSETable>,
    pub(super) of_repeat_valid: bool,
    pub(super) of_default: &'a FSETable,
    pub(super) repeat_table_max_sequences: usize,
    pub(super) llml_predefined_max_sequences: usize,
    pub(super) of_predefined_max_sequences: usize,
    pub(super) of_max_log: u8,
    pub(super) exact_sequence_mode_search: bool,
    pub(super) c_fast_heuristics: bool,
    pub(super) c_cost_model: bool,
}

pub(super) fn exact_sequence_section_size(
    sequences: &[Sequence],
    ll_mode: &FseTableMode<'_>,
    ml_mode: &FseTableMode<'_>,
    of_mode: &FseTableMode<'_>,
) -> usize {
    let mut encoded = Vec::new();
    let mut writer = BitWriter::from(&mut encoded);
    writer.write_bits(encode_fse_table_modes(ll_mode, ml_mode, of_mode), 8).expect("owned legacy codec allocation failed");
    encode_table(ll_mode, &mut writer).expect("owned legacy codec allocation failed");
    encode_table(of_mode, &mut writer).expect("owned legacy codec allocation failed");
    encode_table(ml_mode, &mut writer).expect("owned legacy codec allocation failed");
    encode_sequences(sequences, &mut writer, ll_mode, ml_mode, of_mode).expect("owned legacy codec allocation failed");
    writer.flush().expect("owned legacy codec allocation failed");
    encoded.len()
}

pub(super) fn encode_table(mode: &FseTableMode<'_>, writer: &mut BitWriter<impl crate::workspace::ByteBufferOwner>) -> Result<(), crate::workspace::CapacityError> {
    match mode {
        FseTableMode::Predefined(_) => {}
        FseTableMode::Rle(symbol) => writer.write_bits(*symbol, 8)?,
        FseTableMode::RepeatLast(_) => {}
        FseTableMode::Encoded(table) => table.write_table(writer)?,
    }
    Ok(())
}

pub(super) fn encode_fse_table_modes(
    ll_mode: &FseTableMode<'_>,
    ml_mode: &FseTableMode<'_>,
    of_mode: &FseTableMode<'_>,
) -> u8 {
    fn mode_to_bits(mode: &FseTableMode<'_>) -> u8 {
        match mode {
            FseTableMode::Predefined(_) => 0,
            FseTableMode::Rle(_) => 1,
            FseTableMode::Encoded(_) => 2,
            FseTableMode::RepeatLast(_) => 3,
        }
    }
    mode_to_bits(ll_mode) << 6 | mode_to_bits(of_mode) << 4 | mode_to_bits(ml_mode) << 2
}