lz-string 0.1.1

implementation of lz-string decompression
Documentation
#[macro_use]
mod utils;

mod base64;
mod bitreader;
mod error;

use bitreader::RevBitReader;
use std::char::decode_utf16;
use std::result;

pub use error::{Error, Result};

#[derive(Default)]
struct State {
    n_bits: u8,
    enlarge_in: u64,
    dict: Vec<Vec<u16>>,
    res: Vec<u16>,
    last: (usize, usize),
}

impl State {
    fn reset(&mut self) {
        self.n_bits = 2;
        self.enlarge_in = 5;
        self.dict.clear();
        for i in 0..3 {
            self.dict.push(vec![i]);
        }
        self.res.clear();
        self.last = (0, 0);
    }
}

pub struct Decoder {
    state: State,
}

impl Decoder {
    pub fn new() -> Self {
        let state = State::default();
        Decoder { state }
    }

    pub fn decode_base64_to(&mut self, input: &str, dst: &mut String) -> Result<()> {
        let reader = RevBitReader::from_iter(base64::DecodeIterator::from_str(input));
        self.decode_impl(reader, dst)
    }

    pub fn decode_base64(&mut self, input: &str) -> Result<String> {
        let mut dst = String::new();
        self.decode_base64_to(input, &mut dst).and(Ok(dst))
    }

    pub fn decode_to(&mut self, input: &[u8], dst: &mut String) -> Result<()> {
        let reader = RevBitReader::from_bytes(input);
        self.decode_impl(reader, dst)
    }

    pub fn decode(&mut self, input: &[u8]) -> Result<String> {
        let mut dst = String::new();
        self.decode_to(input, &mut dst).and(Ok(dst))
    }

    pub fn decode_impl<I, E>(&mut self, mut reader: RevBitReader<I>, dst: &mut String) -> Result<()>
    where
        E: Into<Error>,
        I: Iterator<Item = result::Result<u8, E>>,
    {
        self.state.reset();

        let slice = self.state.next(&mut reader)?;
        if slice.is_empty() {
            return Ok(());
        }

        self.state.last = (0, 1);
        self.state.n_bits += 1;

        loop {
            let before = self.state.res.len();
            let slice = self.state.next(&mut reader)?;
            if slice.is_empty() {
                return self.flush(dst);
            }

            let mut last = self.state.res[self.state.last.0..self.state.last.1].to_owned();
            last.push(slice[0]);
            self.state.add_to_dict(&last);

            self.state.last = (before, self.state.res.len());
        }
    }

    fn flush(&mut self, dst: &mut String) -> Result<()> {
        let chars = self.state.res.iter().map(|u| *u);
        for chr in decode_utf16(chars) {
            let chr = chr?;
            dst.push(chr);
        }

        Ok(())
    }
}

impl State {
    fn next<I, E>(&mut self, reader: &mut RevBitReader<I>) -> Result<Vec<u16>>
    where
        E: Into<Error>,
        I: Iterator<Item = result::Result<u8, E>>,
    {
        let bits = take(reader, self.n_bits)?;

        match bits {
            0 => self.litteral(reader, 8),
            1 => self.litteral(reader, 16),
            2 => Ok(vec![]),
            c if (c as usize) < self.dict.len() => self.dict_entry(c as usize),
            c if (c as usize) == self.dict.len() => self.repeat_last(),
            c => Err(Error::InvalidHeader(c)),
        }
    }

    fn litteral<I, E>(&mut self, reader: &mut RevBitReader<I>, n_bits: u8) -> Result<Vec<u16>>
    where
        E: Into<Error>,
        I: Iterator<Item = result::Result<u8, E>>,
    {
        let bits = take(reader, n_bits)? as u16;
        self.add_to_dict(&[bits]);
        self.res.push(bits);
        Ok(self.res[self.res.len() - 1..].to_owned())
    }

    fn dict_entry(&mut self, idx: usize) -> Result<Vec<u16>> {
        let entry = &self.dict[idx];
        self.res.extend(entry);
        Ok(entry.to_owned())
    }

    fn repeat_last(&mut self) -> Result<Vec<u16>> {
        let mut value = self.res[self.last.0..self.last.1].to_owned();
        value.push(value[0]);
        self.res.extend(value.iter());
        Ok(value)
    }

    fn add_to_dict(&mut self, entry: &[u16]) {
        self.dict.push(entry.to_owned());
        self.enlarge_in -= 1;
        if self.enlarge_in == 0 {
            self.enlarge_in = 1 << self.n_bits;
            self.n_bits += 1;
        }
    }
}

fn take<I, E>(reader: &mut RevBitReader<I>, n: u8) -> Result<u64>
where
    E: Into<Error>,
    I: Iterator<Item = result::Result<u8, E>>,
{
    reader
        .take(n)
        .map(|r| r.map_err(Into::into))
        .unwrap_or(Err(Error::UnexpectedEof))
}