#![cfg(feature = "mii")]
use crate::{ChunkIncr, ToChunkIncr};
#[derive(Debug, Clone)]
pub struct Mii {
w: u64,
}
impl Mii {
pub fn with_w(w: u64) -> Self {
Self { w }
}
}
impl Default for Mii {
fn default() -> Self {
Mii::with_w(5)
}
}
impl crate::Chunk for Mii {
type SearchState = MiiSearchState;
fn to_search_state(&self) -> Self::SearchState {
Into::<MiiIncr>::into(self).into()
}
fn find_chunk_edge(
&self,
state: &mut Self::SearchState,
data: &[u8],
) -> (Option<usize>, usize) {
match state.push(data) {
Some(v) => {
state.reset();
(Some(v), v)
}
None => (None, data.len()),
}
}
}
impl From<&Mii> for MiiIncr {
fn from(src: &Mii) -> Self {
src.clone().into()
}
}
impl ToChunkIncr for Mii {
type Incr = MiiIncr;
fn to_chunk_incr(&self) -> Self::Incr {
self.into()
}
}
#[derive(Debug)]
pub struct MiiSearchState {
incr: MiiIncr,
}
impl MiiSearchState {
fn reset(&mut self) {
self.incr.reset();
}
}
impl From<MiiIncr> for MiiSearchState {
fn from(incr: MiiIncr) -> Self {
Self { incr }
}
}
impl MiiSearchState {
fn push(&mut self, data: &[u8]) -> Option<usize> {
self.incr.push(data)
}
}
#[derive(Debug)]
pub struct MiiIncr {
w: u64,
prev: u8,
increment: u64,
}
impl From<Mii> for MiiIncr {
fn from(p: Mii) -> Self {
MiiIncr {
w: p.w,
prev: 0xff,
increment: 0,
}
}
}
impl ChunkIncr for MiiIncr {
fn push(&mut self, input: &[u8]) -> Option<usize> {
for (i, b) in input.iter().cloned().enumerate() {
if b > self.prev {
self.increment += 1;
if self.increment == self.w {
self.increment = 0;
self.prev = 0;
return Some(i + 1);
}
} else {
self.increment = 0;
}
self.prev = b;
}
None
}
}
impl MiiIncr {
fn reset(&mut self) {
self.prev = 0xff;
self.increment = 0;
}
}