#![allow(dead_code)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum BackendTag {
Simple,
Dfast,
Row,
HashChain,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ParseMode {
Greedy,
Lazy,
Lazy2,
Optimal,
}
impl ParseMode {
pub(crate) const fn lazy_depth(self) -> u8 {
match self {
Self::Greedy => 0,
Self::Lazy => 1,
Self::Lazy2 => 2,
Self::Optimal => 0,
}
}
pub(crate) const fn from_lazy_depth(depth: u8) -> Self {
match depth {
0 => Self::Greedy,
1 => Self::Lazy,
_ => Self::Lazy2,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum SearchMethod {
Fast,
DoubleFast,
RowHash,
HashChain,
BinaryTree,
}
impl SearchMethod {
pub(crate) const fn backend(self) -> BackendTag {
match self {
Self::Fast => BackendTag::Simple,
Self::DoubleFast => BackendTag::Dfast,
Self::RowHash => BackendTag::Row,
Self::HashChain | Self::BinaryTree => BackendTag::HashChain,
}
}
}
pub(crate) trait Strategy: Copy + 'static {
const BACKEND: BackendTag;
const MIN_MATCH: usize;
const ACCURATE_PRICE: bool;
const FAVOR_SMALL_OFFSETS: bool;
const USE_HASH3: bool;
const TWO_PASS_SEED: bool = false;
const USE_BT: bool;
const OPT_LEVEL: u8;
const MAX_CHAIN_DEPTH: usize;
const SUFFICIENT_MATCH_LEN: usize;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Fast;
impl Strategy for Fast {
const BACKEND: BackendTag = BackendTag::Simple;
const MIN_MATCH: usize = 4;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = false;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 8;
const SUFFICIENT_MATCH_LEN: usize = 32;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Dfast;
impl Strategy for Dfast {
const BACKEND: BackendTag = BackendTag::Dfast;
const MIN_MATCH: usize = 4;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = false;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 8;
const SUFFICIENT_MATCH_LEN: usize = 32;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Greedy;
impl Strategy for Greedy {
const BACKEND: BackendTag = BackendTag::Row;
const MIN_MATCH: usize = 4;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = false;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 8;
const SUFFICIENT_MATCH_LEN: usize = 32;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Lazy;
impl Strategy for Lazy {
const BACKEND: BackendTag = BackendTag::Row;
const MIN_MATCH: usize = 4;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = false;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 8;
const SUFFICIENT_MATCH_LEN: usize = 32;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Btlazy2;
impl Strategy for Btlazy2 {
const BACKEND: BackendTag = BackendTag::HashChain;
const MIN_MATCH: usize = 5;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = true;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 64;
const SUFFICIENT_MATCH_LEN: usize = usize::MAX;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct BtOpt;
impl Strategy for BtOpt {
const BACKEND: BackendTag = BackendTag::HashChain;
const MIN_MATCH: usize = 4;
const ACCURATE_PRICE: bool = false;
const FAVOR_SMALL_OFFSETS: bool = true;
const USE_HASH3: bool = false;
const USE_BT: bool = true;
const OPT_LEVEL: u8 = 0;
const MAX_CHAIN_DEPTH: usize = 32;
const SUFFICIENT_MATCH_LEN: usize = usize::MAX;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct BtUltra;
impl Strategy for BtUltra {
const BACKEND: BackendTag = BackendTag::HashChain;
const MIN_MATCH: usize = 3;
const ACCURATE_PRICE: bool = true;
const FAVOR_SMALL_OFFSETS: bool = false;
const USE_HASH3: bool = true;
const USE_BT: bool = true;
const OPT_LEVEL: u8 = 2;
const MAX_CHAIN_DEPTH: usize = 64;
const SUFFICIENT_MATCH_LEN: usize = usize::MAX;
}
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct BtUltra2;
impl Strategy for BtUltra2 {
const BACKEND: BackendTag = BackendTag::HashChain;
const MIN_MATCH: usize = 3;
const ACCURATE_PRICE: bool = true;
const FAVOR_SMALL_OFFSETS: bool = false;
const USE_HASH3: bool = true;
const TWO_PASS_SEED: bool = true;
const USE_BT: bool = true;
const OPT_LEVEL: u8 = 2;
const MAX_CHAIN_DEPTH: usize = 512;
const SUFFICIENT_MATCH_LEN: usize = usize::MAX;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum StrategyTag {
Fast,
Dfast,
Greedy,
Lazy,
Btlazy2,
BtOpt,
BtUltra,
BtUltra2,
}
impl StrategyTag {
pub(crate) const fn for_level(level: u8) -> Self {
match level {
1 | 2 => Self::Fast,
3 | 4 => Self::Dfast,
5 => Self::Greedy,
6..=12 => Self::Lazy,
13..=15 => Self::Btlazy2,
16 | 17 => Self::BtOpt,
18 => Self::BtUltra,
19 => Self::BtUltra2,
_ => Self::BtUltra2,
}
}
pub(crate) fn for_compression_level(level: crate::encoding::CompressionLevel) -> Self {
use crate::encoding::CompressionLevel;
match level {
CompressionLevel::Uncompressed => Self::Fast,
CompressionLevel::Fastest => Self::Fast,
CompressionLevel::Default => Self::Dfast,
CompressionLevel::Better => Self::Lazy,
CompressionLevel::Best => Self::Lazy,
CompressionLevel::Level(n) => {
if n <= 0 {
if n == 0 { Self::Dfast } else { Self::Fast }
} else {
let clamped_i32 = n.clamp(1, CompressionLevel::MAX_LEVEL);
Self::for_level(clamped_i32 as u8)
}
}
}
}
pub(crate) const fn backend(self) -> BackendTag {
match self {
Self::Fast => BackendTag::Simple,
Self::Dfast => BackendTag::Dfast,
Self::Greedy | Self::Lazy => BackendTag::Row,
Self::Btlazy2 | Self::BtOpt | Self::BtUltra | Self::BtUltra2 => BackendTag::HashChain,
}
}
pub(crate) const fn search(self) -> SearchMethod {
match self {
Self::Fast => SearchMethod::Fast,
Self::Dfast => SearchMethod::DoubleFast,
Self::Greedy | Self::Lazy => SearchMethod::RowHash,
Self::Btlazy2 | Self::BtOpt | Self::BtUltra | Self::BtUltra2 => {
SearchMethod::BinaryTree
}
}
}
pub(crate) const fn parse_mode(self) -> ParseMode {
match self {
Self::Fast | Self::Dfast | Self::Greedy => ParseMode::Greedy,
Self::Lazy => ParseMode::Lazy,
Self::Btlazy2 => ParseMode::Lazy2,
Self::BtOpt | Self::BtUltra | Self::BtUltra2 => ParseMode::Optimal,
}
}
}
#[cfg(test)]
mod tests;