furze 0.0.1

finite state transducers (fst) writen in rust
Documentation
use crate::encoder::Encoder;
use crate::error::FstError;
use crate::error::FstResult;
use crate::state::State;
use crate::state::{
    BIT_FINAL_STATE, BIT_LAST_STATE, BIT_STATE_HAS_FINAL_OUTPUT, BIT_STATE_HAS_OUPPUT,
    BIT_STOP_NODE, BIT_TAGET_NEXT, BIT_TARGET_DELTA,
};

const DROP_MSB: u8 = 0b0111_1111;
const MSB: u8 = 0b1000_0000;

struct ReverseReader<'a> {
    i: i32,
    data: &'a [u8],
}

impl<'a> ReverseReader<'a> {
    fn new(data: &'a [u8]) -> ReverseReader {
        Self {
            i: (data.len() - 1) as i32,
            data: data,
        }
    }

    fn reset(&mut self) {
        self.i = (self.data.len() - 1) as i32
    }

    fn set_position(&mut self, postion: i32) {
        self.i = postion
    }

    fn read_byte(&mut self) -> FstResult<u8> {
        if self.i < 0 {
            return Err(FstError::Eof);
        }
        let b = self.data[self.i as usize];
        self.i -= 1;
        Ok(b)
    }

    fn get_position(&self) -> i32 {
        self.i
    }
}

pub struct Decoder<'a> {
    reader: ReverseReader<'a>,
}

impl<'a> Decoder<'a> {
    pub fn new(data: &'a [u8]) -> Decoder {
        Self {
            reader: ReverseReader::new(data),
        }
    }

    pub fn reset(&mut self) {
        self.reader.reset()
    }

    pub fn near(&mut self, key: &[u8]) -> FstResult<u64> {
        let mut state = State::new(0, 0);
        self.near_next(key, &mut state)
    }

    fn near_next(&mut self, key: &[u8], state: &mut State) -> FstResult<u64> {
        let mut frist_k = 0;
        if key.len() > 0 {
            frist_k = key[0];
        }
        let mut out: u64 = 0;
        let mut greater: bool = false;
        loop {
            let frist_res = self.near_target_state(frist_k, state);
            let position = self.reader.get_position();
            match frist_res {
                Err(e) => match e {
                    FstError::Greater => {
                        greater = true;
                    }
                    _ => {
                        return Err(FstError::NotFound);
                    }
                },
                Ok(()) => {}
            }
            out += state.out;
            if greater {
                loop {
                    if state.is_final {
                        break;
                    }
                    self.read_first_state(state)?;
                    out += state.out;
                }
                out += state.final_out;
            } else {
                let res = self.near_next(&key[1..], state);
                match res {
                    Ok(_out) => {
                        out += _out;
                    }
                    Err(e) => {
                        if !state.is_last {
                            self.reader.set_position(position);
                            state.reset();
                            continue;
                        }
                        return Err(FstError::NotFound);
                    }
                }
            }
            break;
        }

        Ok(out)
    }

    fn near_target_state(&mut self, _in: u8, state: &mut State) -> FstResult<()> {
        self.read_first_state(state)?;
        loop {
            if state._in == _in {
                return Ok(());
            } else if state._in > _in {
                return Err(FstError::Greater);
            } else if state.is_last {
                return Err(FstError::NotFound);
            } else {
                self.read_next_state(state)?;
            }
        }
    }

    pub fn find(&mut self, key: &[u8]) -> FstResult<u64> {
        let mut state = State::new(0, 0);
        let mut out: u64 = 0;
        for _k in key.iter() {
            self.find_target_state(*_k, &mut state)?;
            out += state.out;
        }
        if !state.is_final {
            return Err(FstError::NotFound);
        }
        out += state.final_out;
        Ok(out)
    }

    fn find_target_state(&mut self, _in: u8, state: &mut State) -> FstResult<()> {
        self.read_first_state(state)?;
        loop {
            if state._in == _in {
                return Ok(());
            } else if state.is_last {
                return Err(FstError::NotFound);
            } else {
                self.read_next_state(state)?;
            }
        }
    }

    fn read_first_state(&mut self, state: &mut State) -> FstResult<()> {
        if state.target > 0 {
            self.reader.set_position(state.target as i32);
        }
        self.read_next_state(state)
    }

    fn read_next_state(&mut self, state: &mut State) -> FstResult<()> {
        state.reset();
        state.flag = self.read_byte()?;
        state._in = self.read_byte()?;
        if state.flag(BIT_STATE_HAS_FINAL_OUTPUT) {
            let (v, _) = self.read_v_u64()?;
            state.final_out = v;
        }

        if state.flag(BIT_STATE_HAS_OUPPUT) {
            let (v, _) = self.read_v_u64()?;
            state.out = v;
        }
        if state.flag(BIT_STOP_NODE) {
            state.is_stop = true;
        } else {
            if !state.flag(BIT_TAGET_NEXT) {
                let (v, _) = self.read_v_u64()?;
                state.target = v;
            }
        }
        if state.flag(BIT_LAST_STATE) {
            state.is_last = true;
        }
        if state.flag(BIT_FINAL_STATE) {
            state.is_final = true;
        }

        Ok(())
    }

    fn read_byte(&mut self) -> FstResult<u8> {
        self.reader.read_byte()
    }

    fn read_v_u64(&mut self) -> FstResult<(u64, usize)> {
        let mut result: u64 = 0;
        let mut shift = 0;
        let mut success = false;
        loop {
            let b = self.read_byte()?;
            let msb_dropped = b & DROP_MSB;
            result |= (msb_dropped as u64) << shift;
            shift += 7;
            if b & MSB == 0 || shift > (9 * 7) {
                success = b & MSB == 0;
                break;
            }
        }
        if success {
            Ok((result, shift / 7 as usize))
        } else {
            Err(FstError::Fail)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_encoder() {}
}