Ver Fonte

Improving Rust performance

Arjun Barrett há 4 anos atrás
pai
commit
2b13b94b78

+ 34 - 51
rs/fflate-wasm/src/lib.rs

@@ -2,59 +2,42 @@ use wasm_bindgen::prelude::*;
 use fflate;
 
 #[wasm_bindgen]
-pub struct Inflate {
-    buf: &'static Vec<u8>,
-    inflator: fflate::Inflate<'static>
+pub fn inflate(dat: &[u8]) -> Vec<u8> {
+    let mut v = Vec::new();
+    fflate::inflate(dat, &mut v);
+    v
 }
 
-#[wasm_bindgen]
-impl Inflate {
-    #[wasm_bindgen(constructor)]
-    pub fn new() -> Inflate {
-        unsafe {
-            static mut buf: Vec<u8> = Vec::new();
-            Inflate {
-                buf: &buf,
-                inflator: fflate::Inflate::new(&mut buf)
-            }
-        }
-    }
-    pub fn push(&mut self, dat: &[u8], last: bool) -> Result<> {
-        self.inflator.write_all(dat);
-    }
-}
-
-
-use std::io::prelude::*;
-use std::env;
-use std::fs::read;
-use std::time;
-use flate2::Compression;
-use flate2::write::DeflateEncoder;
-use flate2::write::DeflateDecoder;
-use libflate::deflate::Decoder;
-mod lib;
+// use std::io::prelude::*;
+// use std::env;
+// use std::fs::read;
+// use std::time;
+// use flate2::Compression;
+// use flate2::write::DeflateEncoder;
+// use flate2::write::DeflateDecoder;
+// use libflate::deflate::Decoder;
+// mod lib;
 
 
 
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let buf = read(&args[1]).unwrap();
-    let mut e = DeflateEncoder::new(Vec::new(), Compression::default());
-    e.write_all(&buf).unwrap();
-    let cmpr = e.finish().unwrap();
-    let t = time::Instant::now();
-    let mut infld = Vec::new();
-    let decmpr = lib::inflate(&cmpr, &mut infld);
-    println!("fflate time: {:?}", t.elapsed());
-    let t2 = time::Instant::now();
-    let mut dec = DeflateDecoder::new(Vec::new());
-    dec.write_all(&cmpr).unwrap();
-    let decmpr2 = dec.finish().unwrap();
-    println!("flate2 time: {:?}", t2.elapsed());
-    let t3 = time::Instant::now();
-    let mut dec = Decoder::new(&*cmpr);
-    let mut decmpr3 = Vec::new();
-    dec.read_to_end(&mut decmpr3).unwrap();
-    println!("libflate time: {:?}", t3.elapsed());
-}
+// fn main() {
+//     let args: Vec<String> = env::args().collect();
+//     let buf = read(&args[1]).unwrap();
+//     let mut e = DeflateEncoder::new(Vec::new(), Compression::default());
+//     e.write_all(&buf).unwrap();
+//     let cmpr = e.finish().unwrap();
+//     let t = time::Instant::now();
+//     let mut infld = Vec::new();
+//     let decmpr = lib::inflate(&cmpr, &mut infld);
+//     println!("fflate time: {:?}", t.elapsed());
+//     let t2 = time::Instant::now();
+//     let mut dec = DeflateDecoder::new(Vec::new());
+//     dec.write_all(&cmpr).unwrap();
+//     let decmpr2 = dec.finish().unwrap();
+//     println!("flate2 time: {:?}", t2.elapsed());
+//     let t3 = time::Instant::now();
+//     let mut dec = Decoder::new(&*cmpr);
+//     let mut decmpr3 = Vec::new();
+//     dec.read_to_end(&mut decmpr3).unwrap();
+//     println!("libflate time: {:?}", t3.elapsed());
+// }

+ 3 - 0
rs/fflate/Cargo.toml

@@ -21,11 +21,14 @@ edition = "2018"
 
 [dependencies]
 lazy_static = "1.4"
+# TO REMOVE
 miniz_oxide = "*"
 
 [profile.release]
 opt-level = 3
 lto = true
+# TO FIX
+debug = true
 
 [features]
 std = []

+ 493 - 0
rs/fflate/src/genlib.rs

@@ -0,0 +1,493 @@
+//! fflate - a fast, efficient, pure compression library
+//!
+//!
+
+// Instead of trying to read this code, check out the TypeScript version
+
+#![allow(non_upper_case_globals)]
+// #![cfg_attr(not(feature = "std"), no_std)]
+use lazy_static::lazy_static;
+
+// #[cfg(feature = "std")]
+use std::{vec::Vec, io::{Read, Write, Error, ErrorKind}, ops::Range};
+
+const fleb: [usize; 32] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0,
+];
+
+const fl: [u16; 32] = [
+    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
+    163, 195, 227, 258, 0, 0, 0,
+];
+
+// in theory, this could be computed, but embedding it at compile time is faster.
+const flt: [u8; 288] = [
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+];
+
+const fdeb: [usize; 32] = [
+    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
+    13, 0, 0,
+];
+
+const fd: [u16; 32] = [
+    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0,
+];
+
+const fdt: [u8; 31] = [5u8; 31];
+
+const clim: [usize; 19] = [
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+];
+
+const et: [u8; 0] = [];
+
+fn freb(b: &[u16], r: &mut [u32]) {
+    for i in 1..30 {
+        let base = b[i];
+        for j in base..b[i + 1] {
+            r[j as usize] = ((j - base) << 5) as u32 | i as u32;
+        }
+    }
+}
+
+// hmap base
+fn hmb(cd: &[u8], mb: u8, le: &mut [u16]) {
+    let t = (mb + 1) as usize;
+    le.iter_mut().for_each(|v| *v = 0);
+    for &cl in cd {
+        if cl != 0 {
+            le[cl as usize] += 1;
+        }
+    }
+    let mut v = 0;
+    for i in 1..t {
+        let val = le[i];
+        le[i] = v;
+        v = (v + val) << 1;
+    }
+}
+
+fn hmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        let v = rev[le[cl] as usize] >> (15 - cl);
+        le[cl] += 1;
+        co[i] = v as u16;
+    }
+}
+
+fn hrmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    let rvb = 15 - mb;
+    let mbu = mb as usize;
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        if cl != 0 {
+            let r = mbu - cl;
+            let v = (le[cl] << r) as usize;
+            le[cl] += 1;
+            let m = v + (1 << r);
+            let sv = ((i as u16) << 4) | cl as u16;
+            rev[v..m].iter().for_each(|i| co[i >> rvb] = sv);
+        }
+    }
+}
+
+lazy_static! {
+    static ref revfl: [u32; 261] = {
+        let mut v = [0u32; 261];
+        freb(&fl, &mut v);
+        v[258] = 28;
+        v
+    };
+    static ref revfd: [u32; 32769] = {
+        let mut v = [0u32; 32769];
+        freb(&fd, &mut v);
+        v
+    };
+    static ref rev: [usize; 32768] = {
+        let mut v = [0usize; 32768];
+        for i in 0..32768 {
+            let mut el = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);
+            el = ((el & 0xCCCC) >> 2) | ((el & 0x3333) << 2);
+            el = ((el & 0xF0F0) >> 4) | ((el & 0x0F0F) << 4);
+            v[i] = (((el & 0xFF00) >> 8) | ((el & 0x00FF) << 8)) >> 1;
+        }
+        v
+    };
+    static ref flm: [u16; 288] = {
+        let mut v = [0u16; 288];
+        hmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref flrm: [u16; 512] = {
+        let mut v = [0u16; 512];
+        hrmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdrm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hrmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+}
+
+#[inline(always)]
+unsafe fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+    let b = pos >> 3;
+    ((*dat.get_unchecked(b) as u16 | ((*dat.get_unchecked(b + 1) as u16) << 8)) >> (pos & 7)) as u8 & mask
+}
+
+#[inline(always)]
+unsafe fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+    let b = pos >> 3;
+    ((*dat.get_unchecked(b) as u32
+        | ((*dat.get_unchecked(b + 1) as u32) << 8)
+        | ((*dat.get_unchecked(b + 2) as u32) << 16))
+        >> (pos & 7)) as u16
+        & mask
+}
+
+#[inline(always)]
+fn shft(pos: usize) -> usize {
+    (pos >> 3) + (pos & 7 != 0) as usize
+}
+
+
+struct InflateState {
+    lmap: [u16; 32768],
+    dmap: [u16; 32768],
+    clmap: [u16; 128],
+    le: [u16; 16],
+    ldt: [u8; 320],
+    clt: [u8; 19],
+    lbits: u8,
+    dbits: u8,
+    bfinal: bool,
+    pos: usize,
+    last: bool,
+    head: bool,
+}
+
+impl InflateState {
+    #[inline(always)]
+    pub fn new() -> Self {
+        Default::default()
+    }
+}
+
+impl Default for InflateState {
+    fn default() -> Self {
+        InflateState {
+            lmap: [0; 32768],
+            dmap: [0; 32768],
+            clmap: [0; 128],
+            le: [0; 16],
+            ldt: [0; 320],
+            clt: [0; 19],
+            lbits: 0,
+            dbits: 0,
+            bfinal: false,
+            pos: 0,
+            last: false,
+            head: true
+        }
+    }
+}
+
+pub enum InflateError {
+    UnexpectedEOF,
+    InvalidBlockType,
+    InvalidLengthOrLiteral,
+    InvalidDistance
+}
+
+// #[cfg(feature = "std")]
+impl From<InflateError> for Error {
+    fn from(error: InflateError) -> Self {
+        Error::new(match error {
+            InflateError::UnexpectedEOF => ErrorKind::UnexpectedEof,
+            _ => ErrorKind::Other
+        }, match error {
+            InflateError::UnexpectedEOF => "unexpected EOF",
+            InflateError::InvalidBlockType => "invalid block type",
+            InflateError::InvalidLengthOrLiteral => "invalid length/literal",
+            InflateError::InvalidDistance => "invalid distance"
+        })
+    }
+}
+
+fn max(dat: &[u8]) -> u8 {
+    let mut m = 0;
+    for &v in dat {
+        if v > m {
+            m = v;
+        }
+    }
+    m
+}
+
+pub trait OutputBuffer {
+    fn write(&mut self, value: u8);
+    fn write_all(&mut self, slice: &[u8]) {
+        for &value in slice {
+            self.write(value);
+        }
+    }
+    fn pre_alloc(&mut self, extra_bytes: usize);
+    fn copy_back(&mut self, back: usize, len: usize);
+}
+
+// #[cfg(feature = "std")]
+impl OutputBuffer for Vec<u8> {
+    #[inline(always)]
+    fn write(&mut self, value: u8) {
+        self.push(value);
+    }
+    #[inline(always)]
+    fn write_all(&mut self, slice: &[u8]) {
+        self.extend_from_slice(slice)
+    }
+    #[inline(always)]
+    fn pre_alloc(&mut self, extra_bytes: usize) {
+        self.reserve(extra_bytes);
+    }
+    #[inline(always)]
+    fn copy_back(&mut self, back: usize, len: usize) {
+        let l = self.len();
+        let st = l - back;
+        self.reserve(len);
+        unsafe {
+            self.set_len(l + len);
+        }
+        if len > back {
+            for i in 0..len {
+                self[l + i] = self[st + i];
+            }
+        } else {
+            self.copy_within(st..st + len, l);
+        }
+    }
+}
+
+// pub struct SliceOutputBuffer<'a > {
+//     buf: &'a mut [u8],
+//     byte: usize
+// }
+
+// impl<'a> SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     pub fn new(slice: &'a mut [u8]) -> SliceOutputBuffer<'a> {
+//         SliceOutputBuffer {
+//             buf: slice,
+//             byte: 0
+//         }
+//     }
+// }
+
+// impl<'a> OutputBuffer for SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     fn write(&mut self, value: u8) {
+//         if self.byte < self.buf.len() {
+//             self.buf[self.byte] = value;
+//         }
+//         self.byte += 1;
+//     }
+//     #[inline(always)]
+//     fn write_all(&mut self, slice: &[u8]) {
+//         let sl = slice.len();
+//         let end = self.byte + sl;
+//         if end <= self.buf.len() {
+//             self.buf[self.byte..end].copy_from_slice(slice);
+//         }
+//         self.byte = end;
+//     }
+//     #[inline(always)]
+//     fn pre_alloc(&mut self, _eb: usize) {}
+//     fn copy_back(&mut self, back: usize, mut len: usize) {
+//         if len > back {
+//             while len != 0 {
+//                 let st = self.byte - back;
+//                 OutputBuffer::write_all(self, &self.buf[st..std::cmp::min(st + len as usize, self.byte)]);
+//                 len -= back;
+//             }
+//         } else {
+//             let st = self.byte - back;
+//             OutputBuffer::write_all(self, &self.buf[st..st + len])
+//         }
+//     }
+
+// }
+
+unsafe fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Result<(), InflateError> {
+    let mut pos = st.pos;
+    let sl = dat.len();
+    if sl == 0 || (st.head && sl < 5) { return Ok(()); }
+    let tbts = sl << 3;
+    loop {
+        if st.head {
+            st.bfinal = bits(dat, pos, 1) != 0;
+            let btype = bits(dat, pos + 1, 3);
+            pos += 3;
+            match btype {
+                0 => {
+                    let s = shft(pos) + 4;
+                    let t = s + (dat[s - 4] as u16 | ((dat[s - 3] as u16) << 8)) as usize;
+                    if t > dat.len() {
+                        if st.last {
+                            return Err(InflateError::UnexpectedEOF);
+                        }
+                        break;
+                    }
+                    buf.write_all(&dat[s..t]);
+                    continue;
+                }
+                1 => {
+                    st.lmap[..512].copy_from_slice(&*flrm);
+                    st.dmap[..32].copy_from_slice(&*fdrm);
+                    st.lbits = 9;
+                    st.dbits = 5;
+                }
+                2 => {
+                    let hlit = bits(dat, pos, 31) as usize + 257;
+                    let hclen = (bits(dat, pos + 10, 15) + 4) as usize;
+                    let tl = hlit + (bits(dat, pos + 5, 31) + 1) as usize;
+                    pos += 14;
+                    for i in 0..hclen {
+                        st.clt[clim[i]] = bits(dat, pos + (i * 3) as usize, 7);
+                    }
+                    pos += hclen * 3;
+                    for i in hclen..19 {
+                        st.clt[clim[i]] = 0;
+                    }
+                    let clb = max(&st.clt);
+                    let clbmsk = (1 << clb) - 1;
+                    if !st.last && pos + tl * (clb + 7) as usize > tbts {
+                        break;
+                    }
+                    hrmap(&st.clt, clb, &mut st.clmap, &mut st.le);
+                    let mut i = 0;
+                    loop {
+                        let r = st.clmap[bits(dat, pos, clbmsk) as usize];
+                        pos += (r & 15) as usize;
+                        let s = (r >> 4) as u8;
+                        if s < 16 {
+                            st.ldt[i] = s;
+                            i += 1;
+                        } else {
+                            let mut c = 0;
+                            let mut n = 0;
+                            if s == 16 {
+                                n = 3 + bits(dat, pos, 3);
+                                pos += 2;
+                                c = st.ldt[i - 1];
+                            }
+                            else if s == 17 {
+                                n = 3 + bits(dat, pos, 7);
+                                pos += 3;
+                            }
+                            else if s == 18 {
+                                n = 11 + bits(dat, pos, 127);
+                                pos += 7;
+                            }
+                            let mut un = n as usize;
+                            i += un;
+                            while un > 0 {
+                                st.ldt[i - un] = c;
+                                un -= 1;
+                            }
+                        }
+                        if i >= tl {
+                            break;
+                        }
+                    }
+                    let lt = &st.ldt[0..hlit];
+                    let dt = &st.ldt[hlit..tl];
+                    st.lbits = max(lt);
+                    st.dbits = max(dt);
+                    hrmap(lt, st.lbits, &mut st.lmap, &mut st.le);
+                    hrmap(dt, st.dbits, &mut st.dmap, &mut st.le);
+                }
+                _ => {
+                    return Err(InflateError::InvalidBlockType);
+                }
+            }
+            if pos > tbts {
+                return Err(InflateError::UnexpectedEOF);   
+            }
+        }
+        st.head = false;
+        let lms = (1u16 << st.lbits) - 1;
+        let dms = (1u16 << st.dbits) - 1;
+        let top = tbts - (st.lbits + st.dbits + 18) as usize;
+        while st.last || pos < top {
+            let c = st.lmap[
+                bits16(dat, pos, lms) as usize
+            ];
+            pos += (c & 15) as usize;
+            let sym = c >> 4;
+            if (sym & 256) == 0 {
+                buf.write(sym as u8);
+            } else if sym == 256 {
+                st.head = true;
+                break;
+            } else {
+                let mut add = sym - 254;
+                if add > 10 {
+                    let i = add as usize - 3;
+                    let b = fleb[i];
+                    add = bits(dat, pos, (1 << b) - 1) as u16 + fl[i];
+                    pos += b;
+                }
+                let d = st.dmap[
+                    bits16(dat, pos, dms) as usize
+                ];
+                if d == 0 {
+                    return Err(InflateError::InvalidDistance);
+                }
+                pos += (d & 15) as usize;
+                let dsym = (d >> 4) as usize;
+                let mut dt = fd[dsym] as usize;
+                if dsym > 3 {
+                    let b = fdeb[dsym];
+                    dt += bits16(dat, pos, (1 << b) - 1) as usize;
+                    pos += b;
+                }
+                if pos > tbts {
+                    return Err(InflateError::UnexpectedEOF);
+                }
+                buf.copy_back(dt, add as usize);
+            }
+        }
+        st.pos = pos;
+        if !st.head || st.bfinal {
+            break;
+        }
+    }
+    Ok(())
+}
+
+pub fn inflate(dat: &[u8], out: &mut dyn OutputBuffer) -> Result<(), InflateError> {
+    let mut st = InflateState::new();
+    st.last = true;
+    unsafe {
+        inflt(dat, out, &mut st)?;
+    }
+    Ok(())
+}

+ 87 - 179
rs/fflate/src/lib.rs

@@ -15,7 +15,7 @@ const fleb: [usize; 32] = [
     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0,
 ];
 
-const fl: [u16; 32] = [
+const fl: [usize; 32] = [
     3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
     163, 195, 227, 258, 0, 0, 0,
 ];
@@ -38,7 +38,7 @@ const fdeb: [usize; 32] = [
     13, 0, 0,
 ];
 
-const fd: [u16; 32] = [
+const fd: [usize; 32] = [
     1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
     2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0,
 ];
@@ -51,7 +51,7 @@ const clim: [usize; 19] = [
 
 const et: [u8; 0] = [];
 
-fn freb(b: &[u16], r: &mut [u32]) {
+fn freb(b: &[usize], r: &mut [u32]) {
     for i in 1..30 {
         let base = b[i];
         for j in base..b[i + 1] {
@@ -99,9 +99,7 @@ fn hrmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
             le[cl] += 1;
             let m = v + (1 << r);
             let sv = ((i as u16) << 4) | cl as u16;
-            for j in v..m {
-                co[rev[j] >> rvb] = sv;
-            }
+            rev[v..m].iter().for_each(|i| co[i >> rvb] = sv);
         }
     }
 }
@@ -151,27 +149,17 @@ lazy_static! {
 }
 
 #[inline(always)]
-fn mbits(dat: &[u8], pos: usize, mask: u8) -> u8 {
-    (dat[pos >> 3] >> (pos & 7)) & mask
-}
-
-fn mbits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+unsafe fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
     let b = pos >> 3;
-    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) & mask
+    ((*dat.get_unchecked(b) as u16 | ((*dat.get_unchecked(b + 1) as u16) << 8)) >> (pos & 7)) as u8 & mask
 }
 
 #[inline(always)]
-fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+unsafe fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
     let b = pos >> 3;
-    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) as u8 & mask
-}
-
-#[inline(always)]
-fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
-    let b = pos >> 3;
-    ((dat[b] as u32
-        | ((dat[b + 1] as u32) << 8)
-        | ((dat[b + 2] as u32) << 16))
+    ((*dat.get_unchecked(b) as u32
+        | ((*dat.get_unchecked(b + 1) as u32) << 8)
+        | ((*dat.get_unchecked(b + 2) as u32) << 16))
         >> (pos & 7)) as u16
         & mask
 }
@@ -255,84 +243,60 @@ fn max(dat: &[u8]) -> u8 {
     m
 }
 
-pub trait OutputBuffer {
-    fn write(&mut self, value: u8);
-    fn write_all(&mut self, slice: &[u8]) {
-        for &value in slice {
-            self.write(value);
-        }
-    }
-    fn pre_alloc(&mut self, extra_bytes: usize);
-    fn back(&self, back: usize) -> u8;
-}
+// pub struct SliceOutputBuffer<'a > {
+//     buf: &'a mut [u8],
+//     byte: usize
+// }
 
-// #[cfg(feature = "std")]
-impl OutputBuffer for Vec<u8> {
-    #[inline(always)]
-    fn write(&mut self, value: u8) {
-        self.push(value);
-    }
-    #[inline(always)]
-    fn write_all(&mut self, slice: &[u8]) {
-        self.extend(slice.iter());
-    }
-    #[inline(always)]
-    fn pre_alloc(&mut self, extra_bytes: usize) {
-        self.reserve(extra_bytes);
-    }
-    #[inline(always)]
-    fn back(&self, back: usize) -> u8 {
-        self[self.len() - back]
-    }
-}
+// impl<'a> SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     pub fn new(slice: &'a mut [u8]) -> SliceOutputBuffer<'a> {
+//         SliceOutputBuffer {
+//             buf: slice,
+//             byte: 0
+//         }
+//     }
+// }
 
-pub struct SliceOutputBuffer<'a > {
-    buf: &'a mut [u8],
-    byte: usize
-}
+// impl<'a> OutputBuffer for SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     fn write(&mut self, value: u8) {
+//         if self.byte < self.buf.len() {
+//             self.buf[self.byte] = value;
+//         }
+//         self.byte += 1;
+//     }
+//     #[inline(always)]
+//     fn write_all(&mut self, slice: &[u8]) {
+//         let sl = slice.len();
+//         let end = self.byte + sl;
+//         if end <= self.buf.len() {
+//             self.buf[self.byte..end].copy_from_slice(slice);
+//         }
+//         self.byte = end;
+//     }
+//     #[inline(always)]
+//     fn pre_alloc(&mut self, _eb: usize) {}
+//     fn copy_back(&mut self, back: usize, mut len: usize) {
+//         if len > back {
+//             while len != 0 {
+//                 let st = self.byte - back;
+//                 OutputBuffer::write_all(self, &self.buf[st..std::cmp::min(st + len as usize, self.byte)]);
+//                 len -= back;
+//             }
+//         } else {
+//             let st = self.byte - back;
+//             OutputBuffer::write_all(self, &self.buf[st..st + len])
+//         }
+//     }
 
-impl<'a> SliceOutputBuffer<'a> {
-    #[inline(always)]
-    pub fn new(slice: &'a mut [u8]) -> SliceOutputBuffer<'a> {
-        SliceOutputBuffer {
-            buf: slice,
-            byte: 0
-        }
-    }
-}
+// }
 
-impl<'a> OutputBuffer for SliceOutputBuffer<'a> {
-    #[inline(always)]
-    fn write(&mut self, value: u8) {
-        if self.byte < self.buf.len() {
-            self.buf[self.byte] = value;
-        }
-        self.byte += 1;
-    }
-    #[inline(always)]
-    fn write_all(&mut self, slice: &[u8]) {
-        let sl = slice.len();
-        let end = self.byte + sl;
-        if end <= self.buf.len() {
-            self.buf[self.byte..end].copy_from_slice(slice);
-        }
-        self.byte = end;
-    }
-    #[inline(always)]
-    fn pre_alloc(&mut self, _eb: usize) {}
-    #[inline(always)]
-    fn back(&self, back: usize) -> u8 {
-        self.buf[self.byte - back]
-    }
-}
-
-fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Result<(), InflateError> {
+unsafe fn inflt(dat: &[u8], buf: &mut Vec<u8>, st: &mut InflateState) -> Result<(), InflateError> {
     let mut pos = st.pos;
     let sl = dat.len();
     if sl == 0 || (st.head && sl < 5) { return Ok(()); }
     let tbts = sl << 3;
-    let tbts1 = tbts - 8;
-    let tbts2 = tbts1 - 8;
     loop {
         if st.head {
             st.bfinal = bits(dat, pos, 1) != 0;
@@ -348,7 +312,7 @@ fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Resul
                         }
                         break;
                     }
-                    buf.write_all(&dat[s..t]);
+                    buf.extend_from_slice(&dat[s..t]);
                     continue;
                 }
                 1 => {
@@ -427,64 +391,35 @@ fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Resul
         }
         st.head = false;
         let lms = (1u16 << st.lbits) - 1;
-        let lms8 = lms as u8;
         let dms = (1u16 << st.dbits) - 1;
-        let dms8 = dms as u8;
-        let topl = tbts - st.lbits as usize;
-        let topd = tbts - st.dbits as usize;
         let top = tbts - (st.lbits + st.dbits + 18) as usize;
-        while st.last || pos < top {
-            let c = st.lmap[
-                if pos > topl {
-                    return Err(InflateError::UnexpectedEOF);
-                } else if st.lbits < 10 {
-                    if pos > tbts1 {
-                        mbits(dat, pos, lms8) as usize
-                    } else {
-                        bits(dat, pos, lms8) as usize
-                    }
-                } else {
-                    if pos > tbts2 {
-                        mbits16(dat, pos, lms) as usize
-                    } else {
-                        bits16(dat, pos, lms) as usize
-                    }
-                }
+        let lm = st.lmap;
+        let dm = st.dmap;
+        let lst = st.last;
+        while lst || pos < top {
+            let c = lm[
+                bits16(dat, pos, lms) as usize
             ];
-            pos += (c & 15) as usize;
             if c == 0 {
                 return Err(InflateError::InvalidLengthOrLiteral);
             }
+            pos += (c & 15) as usize;
             let sym = c >> 4;
-            if (sym >> 8) == 0 {
-                buf.write(sym as u8);
+            if (sym & 256) == 0 {
+                buf.push(sym as u8);
             } else if sym == 256 {
                 st.head = true;
                 break;
             } else {
-                let mut add = sym - 254;
+                let mut add = (sym as usize) - 254;
                 if add > 10 {
-                    let i = add as usize - 3;
+                    let i = add - 3;
                     let b = fleb[i];
-                    add = bits(dat, pos, (1 << b) - 1) as u16 + fl[i];
+                    add = bits(dat, pos, (1 << b) - 1) as usize + fl[i];
                     pos += b;
                 }
-                let d = st.dmap[
-                    if pos > topd {
-                        return Err(InflateError::UnexpectedEOF);
-                    } else if st.dbits < 10 {
-                        if pos > tbts1 {
-                            mbits(dat, pos, dms8) as usize
-                        } else {
-                            bits(dat, pos, dms8) as usize
-                        }
-                    } else {
-                        if pos > tbts2 {
-                            mbits16(dat, pos, dms) as usize
-                        } else {
-                            bits16(dat, pos, dms) as usize
-                        }
-                    }
+                let d = dm[
+                    bits16(dat, pos, dms) as usize
                 ];
                 if d == 0 {
                     return Err(InflateError::InvalidDistance);
@@ -500,9 +435,17 @@ fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Resul
                 if pos > tbts {
                     return Err(InflateError::UnexpectedEOF);
                 }
-                while add != 0 {
-                    buf.write(buf.back(dt));
-                    add -= 1;
+                let len = add as usize;
+                let l = buf.len();
+                let st = l - dt;
+                buf.reserve(len);
+                buf.set_len(l + len);
+                if len > dt {
+                    for i in 0..len {
+                        buf[l + i] = buf[st + i];
+                    }
+                } else {
+                    buf.copy_within(st..st + len, l);
                 }
             }
         }
@@ -514,46 +457,11 @@ fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Resul
     Ok(())
 }
 
-pub fn inflate(dat: &[u8], out: &mut dyn OutputBuffer) -> Result<(), InflateError> {
+pub fn inflate(dat: &[u8], out: &mut Vec<u8>) -> Result<(), InflateError> {
     let mut st = InflateState::new();
     st.last = true;
-    inflt(dat, out, &mut st)?;
+    unsafe {
+        inflt(dat, out, &mut st)?;
+    }
     Ok(())
-}
-
-// // pub struct Inflate<'a> {
-// //     pub sink: &'a mut dyn OutputBuffer,
-// //     state: InflateState
-// // }
-
-// // impl<'a> Inflate<'a> {
-// //     pub fn push(&mut self, data: &[u8]) -> Result<usize, InflateError> {
-// //         inflt(data, self.sink, &mut self.state)?;
-// //         let bytes = self.state.pos >> 3;
-// //         self.state.pos &= 7;
-// //         Ok(bytes)
-// //     }
-// //     pub fn end(&mut self) -> Result<(), InflateError> {
-// //         self.state.last = true;
-// //         self.push(&et)?;
-// //         Ok(())
-// //     }
-// //     pub fn new(sink: &'a mut dyn OutputBuffer) -> Inflate<'a> {
-// //         Inflate {
-// //             state: InflateState::new(),
-// //             sink: sink
-// //         }
-// //     }
-// // }
-
-// #[cfg(feature = "std")]
-// impl<'a> Write for Inflate<'a> {
-//     #[inline(always)]
-//     fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
-//         Ok(self.push(data)?)
-//     }
-//     #[inline(always)]
-//     fn flush(&mut self) -> Result<(), Error> {
-//         Ok(self.end()?)
-//     }
-// }
+}

+ 20 - 0
rs/fflate/src/main.rs

@@ -0,0 +1,20 @@
+use std::fs;
+use std::env;
+use std::time;
+use std::string;
+extern crate miniz_oxide;
+mod lib;
+
+
+fn main() {
+    let args = env::args().collect::<Vec<String>>();
+    let fp = args.get(1).unwrap();
+    let dat = fs::read(fp).unwrap();
+    let mut out = Vec::new();
+    let ts = time::Instant::now();
+    lib::inflate(&dat, &mut out);
+    println!("{:?} {}", ts.elapsed(), out.len());
+    let ts = time::Instant::now();
+    let o2 = miniz_oxide::inflate::decompress_to_vec(&dat).unwrap();
+    println!("{:?}", ts.elapsed());
+}

+ 559 - 0
rs/fflate/src/newlib.rs

@@ -0,0 +1,559 @@
+//! fflate - a fast, efficient, pure compression library
+//!
+//!
+
+// Instead of trying to read this code, check out the TypeScript version
+
+#![allow(non_upper_case_globals)]
+// #![cfg_attr(not(feature = "std"), no_std)]
+use lazy_static::lazy_static;
+
+// #[cfg(feature = "std")]
+use std::{vec::Vec, io::{Read, Write, Error, ErrorKind}, ops::Range};
+
+const fleb: [usize; 32] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0,
+];
+
+const fl: [u16; 32] = [
+    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
+    163, 195, 227, 258, 0, 0, 0,
+];
+
+// in theory, this could be computed, but embedding it at compile time is faster.
+const flt: [u8; 288] = [
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+];
+
+const fdeb: [usize; 32] = [
+    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
+    13, 0, 0,
+];
+
+const fd: [u16; 32] = [
+    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0,
+];
+
+const fdt: [u8; 31] = [5u8; 31];
+
+const clim: [usize; 19] = [
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+];
+
+const et: [u8; 0] = [];
+
+fn freb(b: &[u16], r: &mut [u32]) {
+    for i in 1..30 {
+        let base = b[i];
+        for j in base..b[i + 1] {
+            r[j as usize] = ((j - base) << 5) as u32 | i as u32;
+        }
+    }
+}
+
+// hmap base
+fn hmb(cd: &[u8], mb: u8, le: &mut [u16]) {
+    let t = (mb + 1) as usize;
+    le.iter_mut().for_each(|v| *v = 0);
+    for &cl in cd {
+        if cl != 0 {
+            le[cl as usize] += 1;
+        }
+    }
+    let mut v = 0;
+    for i in 1..t {
+        let val = le[i];
+        le[i] = v;
+        v = (v + val) << 1;
+    }
+}
+
+fn hmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        let v = rev[le[cl] as usize] >> (15 - cl);
+        le[cl] += 1;
+        co[i] = v as u16;
+    }
+}
+
+fn hrmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    let rvb = 15 - mb;
+    let mbu = mb as usize;
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        if cl != 0 {
+            let r = mbu - cl;
+            let v = (le[cl] << r) as usize;
+            le[cl] += 1;
+            let m = v + (1 << r);
+            let sv = ((i as u16) << 4) | cl as u16;
+            for j in v..m {
+                co[rev[j] >> rvb] = sv;
+            }
+        }
+    }
+}
+
+lazy_static! {
+    static ref revfl: [u32; 261] = {
+        let mut v = [0u32; 261];
+        freb(&fl, &mut v);
+        v[258] = 28;
+        v
+    };
+    static ref revfd: [u32; 32769] = {
+        let mut v = [0u32; 32769];
+        freb(&fd, &mut v);
+        v
+    };
+    static ref rev: [usize; 32768] = {
+        let mut v = [0usize; 32768];
+        for i in 0..32768 {
+            let mut el = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);
+            el = ((el & 0xCCCC) >> 2) | ((el & 0x3333) << 2);
+            el = ((el & 0xF0F0) >> 4) | ((el & 0x0F0F) << 4);
+            v[i] = (((el & 0xFF00) >> 8) | ((el & 0x00FF) << 8)) >> 1;
+        }
+        v
+    };
+    static ref flm: [u16; 288] = {
+        let mut v = [0u16; 288];
+        hmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref flrm: [u16; 512] = {
+        let mut v = [0u16; 512];
+        hrmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdrm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hrmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+}
+
+#[inline(always)]
+fn mbits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+    (dat[pos >> 3] >> (pos & 7)) & mask
+}
+
+fn mbits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+    let b = pos >> 3;
+    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) & mask
+}
+
+#[inline(always)]
+fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+    let b = pos >> 3;
+    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) as u8 & mask
+}
+
+#[inline(always)]
+fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+    let b = pos >> 3;
+    ((dat[b] as u32
+        | ((dat[b + 1] as u32) << 8)
+        | ((dat[b + 2] as u32) << 16))
+        >> (pos & 7)) as u16
+        & mask
+}
+
+#[inline(always)]
+fn shft(pos: usize) -> usize {
+    (pos >> 3) + (pos & 7 != 0) as usize
+}
+
+
+struct InflateState {
+    lmap: [u16; 32768],
+    dmap: [u16; 32768],
+    clmap: [u16; 128],
+    le: [u16; 16],
+    ldt: [u8; 320],
+    clt: [u8; 19],
+    lbits: u8,
+    dbits: u8,
+    bfinal: bool,
+    pos: usize,
+    last: bool,
+    head: bool,
+}
+
+impl InflateState {
+    #[inline(always)]
+    pub fn new() -> Self {
+        Default::default()
+    }
+}
+
+impl Default for InflateState {
+    fn default() -> Self {
+        InflateState {
+            lmap: [0; 32768],
+            dmap: [0; 32768],
+            clmap: [0; 128],
+            le: [0; 16],
+            ldt: [0; 320],
+            clt: [0; 19],
+            lbits: 0,
+            dbits: 0,
+            bfinal: false,
+            pos: 0,
+            last: false,
+            head: true
+        }
+    }
+}
+
+pub enum InflateError {
+    UnexpectedEOF,
+    InvalidBlockType,
+    InvalidLengthOrLiteral,
+    InvalidDistance
+}
+
+// #[cfg(feature = "std")]
+impl From<InflateError> for Error {
+    fn from(error: InflateError) -> Self {
+        Error::new(match error {
+            InflateError::UnexpectedEOF => ErrorKind::UnexpectedEof,
+            _ => ErrorKind::Other
+        }, match error {
+            InflateError::UnexpectedEOF => "unexpected EOF",
+            InflateError::InvalidBlockType => "invalid block type",
+            InflateError::InvalidLengthOrLiteral => "invalid length/literal",
+            InflateError::InvalidDistance => "invalid distance"
+        })
+    }
+}
+
+fn max(dat: &[u8]) -> u8 {
+    let mut m = 0;
+    for &v in dat {
+        if v > m {
+            m = v;
+        }
+    }
+    m
+}
+
+pub trait OutputBuffer {
+    fn write(&mut self, value: u8);
+    fn write_all(&mut self, slice: &[u8]) {
+        for &value in slice {
+            self.write(value);
+        }
+    }
+    fn pre_alloc(&mut self, extra_bytes: usize);
+    fn back(&self, back: usize) -> u8;
+}
+
+// #[cfg(feature = "std")]
+impl OutputBuffer for Vec<u8> {
+    #[inline(always)]
+    fn write(&mut self, value: u8) {
+        self.push(value);
+    }
+    #[inline(always)]
+    fn write_all(&mut self, slice: &[u8]) {
+        self.extend(slice.iter());
+    }
+    #[inline(always)]
+    fn pre_alloc(&mut self, extra_bytes: usize) {
+        self.reserve(extra_bytes);
+    }
+    #[inline(always)]
+    fn back(&self, back: usize) -> u8 {
+        self[self.len() - back]
+    }
+}
+
+pub struct SliceOutputBuffer<'a > {
+    buf: &'a mut [u8],
+    byte: usize
+}
+
+impl<'a> SliceOutputBuffer<'a> {
+    #[inline(always)]
+    pub fn new(slice: &'a mut [u8]) -> SliceOutputBuffer<'a> {
+        SliceOutputBuffer {
+            buf: slice,
+            byte: 0
+        }
+    }
+}
+
+impl<'a> OutputBuffer for SliceOutputBuffer<'a> {
+    #[inline(always)]
+    fn write(&mut self, value: u8) {
+        if self.byte < self.buf.len() {
+            self.buf[self.byte] = value;
+        }
+        self.byte += 1;
+    }
+    #[inline(always)]
+    fn write_all(&mut self, slice: &[u8]) {
+        let sl = slice.len();
+        let end = self.byte + sl;
+        if end <= self.buf.len() {
+            self.buf[self.byte..end].copy_from_slice(slice);
+        }
+        self.byte = end;
+    }
+    #[inline(always)]
+    fn pre_alloc(&mut self, _eb: usize) {}
+    #[inline(always)]
+    fn back(&self, back: usize) -> u8 {
+        self.buf[self.byte - back]
+    }
+}
+
+fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Result<(), InflateError> {
+    let mut pos = st.pos;
+    let sl = dat.len();
+    if sl == 0 || (st.head && sl < 5) { return Ok(()); }
+    let tbts = sl << 3;
+    let tbts1 = tbts - 8;
+    let tbts2 = tbts1 - 8;
+    loop {
+        if st.head {
+            st.bfinal = bits(dat, pos, 1) != 0;
+            let btype = bits(dat, pos + 1, 3);
+            pos += 3;
+            match btype {
+                0 => {
+                    let s = shft(pos) + 4;
+                    let t = s + (dat[s - 4] as u16 | ((dat[s - 3] as u16) << 8)) as usize;
+                    if t > dat.len() {
+                        if st.last {
+                            return Err(InflateError::UnexpectedEOF);
+                        }
+                        break;
+                    }
+                    buf.write_all(&dat[s..t]);
+                    continue;
+                }
+                1 => {
+                    st.lmap[..512].copy_from_slice(&*flrm);
+                    st.dmap[..32].copy_from_slice(&*fdrm);
+                    st.lbits = 9;
+                    st.dbits = 5;
+                }
+                2 => {
+                    let hlit = bits(dat, pos, 31) as usize + 257;
+                    let hclen = (bits(dat, pos + 10, 15) + 4) as usize;
+                    let tl = hlit + (bits(dat, pos + 5, 31) + 1) as usize;
+                    pos += 14;
+                    for i in 0..hclen {
+                        st.clt[clim[i]] = bits(dat, pos + (i * 3) as usize, 7);
+                    }
+                    pos += hclen * 3;
+                    for i in hclen..19 {
+                        st.clt[clim[i]] = 0;
+                    }
+                    let clb = max(&st.clt);
+                    let clbmsk = (1 << clb) - 1;
+                    if !st.last && pos + tl * (clb + 7) as usize > tbts {
+                        break;
+                    }
+                    hrmap(&st.clt, clb, &mut st.clmap, &mut st.le);
+                    let mut i = 0;
+                    loop {
+                        let r = st.clmap[bits(dat, pos, clbmsk) as usize];
+                        pos += (r & 15) as usize;
+                        let s = (r >> 4) as u8;
+                        if s < 16 {
+                            st.ldt[i] = s;
+                            i += 1;
+                        } else {
+                            let mut c = 0;
+                            let mut n = 0;
+                            if s == 16 {
+                                n = 3 + bits(dat, pos, 3);
+                                pos += 2;
+                                c = st.ldt[i - 1];
+                            }
+                            else if s == 17 {
+                                n = 3 + bits(dat, pos, 7);
+                                pos += 3;
+                            }
+                            else if s == 18 {
+                                n = 11 + bits(dat, pos, 127);
+                                pos += 7;
+                            }
+                            let mut un = n as usize;
+                            i += un;
+                            while un > 0 {
+                                st.ldt[i - un] = c;
+                                un -= 1;
+                            }
+                        }
+                        if i >= tl {
+                            break;
+                        }
+                    }
+                    let lt = &st.ldt[0..hlit];
+                    let dt = &st.ldt[hlit..tl];
+                    st.lbits = max(lt);
+                    st.dbits = max(dt);
+                    hrmap(lt, st.lbits, &mut st.lmap, &mut st.le);
+                    hrmap(dt, st.dbits, &mut st.dmap, &mut st.le);
+                }
+                _ => {
+                    return Err(InflateError::InvalidBlockType);
+                }
+            }
+            if pos > tbts {
+                return Err(InflateError::UnexpectedEOF);   
+            }
+        }
+        st.head = false;
+        let lms = (1u16 << st.lbits) - 1;
+        let lms8 = lms as u8;
+        let dms = (1u16 << st.dbits) - 1;
+        let dms8 = dms as u8;
+        let topl = tbts - st.lbits as usize;
+        let topd = tbts - st.dbits as usize;
+        let top = tbts - (st.lbits + st.dbits + 18) as usize;
+        while st.last || pos < top {
+            let c = st.lmap[
+                if pos > topl {
+                    return Err(InflateError::UnexpectedEOF);
+                } else if st.lbits < 10 {
+                    if pos > tbts1 {
+                        mbits(dat, pos, lms8) as usize
+                    } else {
+                        bits(dat, pos, lms8) as usize
+                    }
+                } else {
+                    if pos > tbts2 {
+                        mbits16(dat, pos, lms) as usize
+                    } else {
+                        bits16(dat, pos, lms) as usize
+                    }
+                }
+            ];
+            pos += (c & 15) as usize;
+            if c == 0 {
+                return Err(InflateError::InvalidLengthOrLiteral);
+            }
+            let sym = c >> 4;
+            if (sym >> 8) == 0 {
+                buf.write(sym as u8);
+            } else if sym == 256 {
+                st.head = true;
+                break;
+            } else {
+                let mut add = sym - 254;
+                if add > 10 {
+                    let i = add as usize - 3;
+                    let b = fleb[i];
+                    add = bits(dat, pos, (1 << b) - 1) as u16 + fl[i];
+                    pos += b;
+                }
+                let d = st.dmap[
+                    if pos > topd {
+                        return Err(InflateError::UnexpectedEOF);
+                    } else if st.dbits < 10 {
+                        if pos > tbts1 {
+                            mbits(dat, pos, dms8) as usize
+                        } else {
+                            bits(dat, pos, dms8) as usize
+                        }
+                    } else {
+                        if pos > tbts2 {
+                            mbits16(dat, pos, dms) as usize
+                        } else {
+                            bits16(dat, pos, dms) as usize
+                        }
+                    }
+                ];
+                if d == 0 {
+                    return Err(InflateError::InvalidDistance);
+                }
+                pos += (d & 15) as usize;
+                let dsym = (d >> 4) as usize;
+                let mut dt = fd[dsym] as usize;
+                if dsym > 3 {
+                    let b = fdeb[dsym];
+                    dt += bits16(dat, pos, (1 << b) - 1) as usize;
+                    pos += b;
+                }
+                if pos > tbts {
+                    return Err(InflateError::UnexpectedEOF);
+                }
+                while add != 0 {
+                    buf.write(buf.back(dt));
+                    add -= 1;
+                }
+            }
+        }
+        st.pos = pos;
+        if !st.head || st.bfinal {
+            break;
+        }
+    }
+    Ok(())
+}
+
+pub fn inflate(dat: &[u8], out: &mut dyn OutputBuffer) -> Result<(), InflateError> {
+    let mut st = InflateState::new();
+    st.last = true;
+    inflt(dat, out, &mut st)?;
+    Ok(())
+}
+
+// // pub struct Inflate<'a> {
+// //     pub sink: &'a mut dyn OutputBuffer,
+// //     state: InflateState
+// // }
+
+// // impl<'a> Inflate<'a> {
+// //     pub fn push(&mut self, data: &[u8]) -> Result<usize, InflateError> {
+// //         inflt(data, self.sink, &mut self.state)?;
+// //         let bytes = self.state.pos >> 3;
+// //         self.state.pos &= 7;
+// //         Ok(bytes)
+// //     }
+// //     pub fn end(&mut self) -> Result<(), InflateError> {
+// //         self.state.last = true;
+// //         self.push(&et)?;
+// //         Ok(())
+// //     }
+// //     pub fn new(sink: &'a mut dyn OutputBuffer) -> Inflate<'a> {
+// //         Inflate {
+// //             state: InflateState::new(),
+// //             sink: sink
+// //         }
+// //     }
+// // }
+
+// #[cfg(feature = "std")]
+// impl<'a> Write for Inflate<'a> {
+//     #[inline(always)]
+//     fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
+//         Ok(self.push(data)?)
+//     }
+//     #[inline(always)]
+//     fn flush(&mut self) -> Result<(), Error> {
+//         Ok(self.end()?)
+//     }
+// }

+ 507 - 0
rs/fflate/src/oldlib.rs

@@ -0,0 +1,507 @@
+//! fflate - a fast, efficient, pure compression library
+//!
+//!
+
+// Instead of trying to read this code, check out the TypeScript version
+
+#![allow(non_upper_case_globals)]
+// #![cfg_attr(not(feature = "std"), no_std)]
+use lazy_static::lazy_static;
+
+// #[cfg(feature = "std")]
+use std::{vec::Vec, io::{Read, Write, Error, ErrorKind}, ops::Range};
+
+const fleb: [usize; 32] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0,
+];
+
+const fl: [u16; 32] = [
+    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
+    163, 195, 227, 258, 0, 0, 0,
+];
+
+// in theory, this could be computed, but embedding it at compile time is faster.
+const flt: [u8; 288] = [
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+];
+
+const fdeb: [usize; 32] = [
+    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
+    13, 0, 0,
+];
+
+const fd: [u16; 32] = [
+    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0,
+];
+
+const fdt: [u8; 31] = [5u8; 31];
+
+const clim: [usize; 19] = [
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+];
+
+const et: [u8; 0] = [];
+
+fn freb(b: &[u16], r: &mut [u32]) {
+    for i in 1..30 {
+        let base = b[i];
+        for j in base..b[i + 1] {
+            r[j as usize] = ((j - base) << 5) as u32 | i as u32;
+        }
+    }
+}
+
+// hmap base
+fn hmb(cd: &[u8], mb: u8, le: &mut [u16]) {
+    let t = (mb + 1) as usize;
+    le.iter_mut().for_each(|v| *v = 0);
+    for &cl in cd {
+        if cl != 0 {
+            le[cl as usize] += 1;
+        }
+    }
+    let mut v = 0;
+    for i in 1..t {
+        let val = le[i];
+        le[i] = v;
+        v = (v + val) << 1;
+    }
+}
+
+fn hmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        let v = rev[le[cl] as usize] >> (15 - cl);
+        le[cl] += 1;
+        co[i] = v as u16;
+    }
+}
+
+fn hrmap(cd: &[u8], mb: u8, co: &mut [u16], le: &mut [u16]) {
+    hmb(cd, mb, le);
+    let rvb = 15 - mb;
+    let mbu = mb as usize;
+    for i in 0..cd.len() {
+        let cl = cd[i] as usize;
+        if cl != 0 {
+            let r = mbu - cl;
+            let v = (le[cl] << r) as usize;
+            le[cl] += 1;
+            let m = v + (1 << r);
+            let sv = ((i as u16) << 4) | cl as u16;
+            rev[v..m].iter().for_each(|i| co[i >> rvb] = sv);
+        }
+    }
+}
+
+lazy_static! {
+    static ref revfl: [u32; 261] = {
+        let mut v = [0u32; 261];
+        freb(&fl, &mut v);
+        v[258] = 28;
+        v
+    };
+    static ref revfd: [u32; 32769] = {
+        let mut v = [0u32; 32769];
+        freb(&fd, &mut v);
+        v
+    };
+    static ref rev: [usize; 32768] = {
+        let mut v = [0usize; 32768];
+        for i in 0..32768 {
+            let mut el = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);
+            el = ((el & 0xCCCC) >> 2) | ((el & 0x3333) << 2);
+            el = ((el & 0xF0F0) >> 4) | ((el & 0x0F0F) << 4);
+            v[i] = (((el & 0xFF00) >> 8) | ((el & 0x00FF) << 8)) >> 1;
+        }
+        v
+    };
+    static ref flm: [u16; 288] = {
+        let mut v = [0u16; 288];
+        hmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref flrm: [u16; 512] = {
+        let mut v = [0u16; 512];
+        hrmap(&flt, 9, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+    static ref fdrm: [u16; 32] = {
+        let mut v = [0u16; 32];
+        hrmap(&fdt, 5, &mut v, &mut [0u16; 16]);
+        v
+    };
+}
+
+#[inline(always)]
+fn mbits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+    (dat[pos >> 3] >> (pos & 7)) & mask
+}
+
+fn mbits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+    let b = pos >> 3;
+    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) & mask
+}
+
+#[inline(always)]
+fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
+    let b = pos >> 3;
+    ((dat[b] as u16 | ((dat[b + 1] as u16) << 8)) >> (pos & 7)) as u8 & mask
+}
+
+#[inline(always)]
+fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
+    let b = pos >> 3;
+    ((dat[b] as u32
+        | ((dat[b + 1] as u32) << 8)
+        | ((dat[b + 2] as u32) << 16))
+        >> (pos & 7)) as u16
+        & mask
+}
+
+#[inline(always)]
+fn shft(pos: usize) -> usize {
+    (pos >> 3) + (pos & 7 != 0) as usize
+}
+
+
+struct InflateState {
+    lmap: [u16; 32768],
+    dmap: [u16; 32768],
+    lbits: u8,
+    dbits: u8,
+    bfinal: bool,
+    pos: usize,
+    last: bool,
+    head: bool,
+}
+
+impl InflateState {
+    #[inline(always)]
+    pub fn new() -> Self {
+        Default::default()
+    }
+}
+
+impl Default for InflateState {
+    fn default() -> Self {
+        InflateState {
+            lmap: [0; 32768],
+            dmap: [0; 32768],
+            lbits: 0,
+            dbits: 0,
+            bfinal: false,
+            pos: 0,
+            last: false,
+            head: true
+        }
+    }
+}
+
+pub enum InflateError {
+    UnexpectedEOF,
+    InvalidBlockType,
+    InvalidLengthOrLiteral,
+    InvalidDistance
+}
+
+// #[cfg(feature = "std")]
+impl From<InflateError> for Error {
+    fn from(error: InflateError) -> Self {
+        Error::new(match error {
+            InflateError::UnexpectedEOF => ErrorKind::UnexpectedEof,
+            _ => ErrorKind::Other
+        }, match error {
+            InflateError::UnexpectedEOF => "unexpected EOF",
+            InflateError::InvalidBlockType => "invalid block type",
+            InflateError::InvalidLengthOrLiteral => "invalid length/literal",
+            InflateError::InvalidDistance => "invalid distance"
+        })
+    }
+}
+
+fn max(dat: &[u8]) -> u8 {
+    let mut m = 0;
+    for &v in dat {
+        if v > m {
+            m = v;
+        }
+    }
+    m
+}
+
+pub trait OutputBuffer {
+    fn write(&mut self, value: u8);
+    fn write_all(&mut self, slice: &[u8]) {
+        for &value in slice {
+            self.write(value);
+        }
+    }
+    fn pre_alloc(&mut self, extra_bytes: usize);
+    fn copy_back(&mut self, back: usize, len: usize);
+}
+
+// #[cfg(feature = "std")]
+impl OutputBuffer for Vec<u8> {
+    #[inline(always)]
+    fn write(&mut self, value: u8) {
+        self.push(value);
+    }
+    #[inline(always)]
+    fn write_all(&mut self, slice: &[u8]) {
+        self.extend(slice.iter());
+    }
+    #[inline(always)]
+    fn pre_alloc(&mut self, extra_bytes: usize) {
+        self.reserve(extra_bytes);
+    }
+    fn copy_back(&mut self, back: usize, mut len: usize) {
+        let no_cp = len > back;
+        let l = self.len();
+        let st = l - back;
+        if no_cp && back < 4 {
+            for i in 0..len {
+                OutputBuffer::write(self, self[st + i]);
+            }
+        } else {
+            let buf = &mut [0u8; 258];
+            if no_cp {
+                while len != 0 {
+                    let add = std::cmp::min(len, back);
+                    buf[0..add].copy_from_slice(&self[st..st + add]);
+                    OutputBuffer::write_all(self, &buf[0..add]);
+                    len -= add;
+                }
+            } else {
+                buf[0..len].copy_from_slice(&self[st..st + len]);
+                OutputBuffer::write_all(self, &buf[0..len]);
+            }
+        }
+    }
+}
+
+// pub struct SliceOutputBuffer<'a > {
+//     buf: &'a mut [u8],
+//     byte: usize
+// }
+
+// impl<'a> SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     pub fn new(slice: &'a mut [u8]) -> SliceOutputBuffer<'a> {
+//         SliceOutputBuffer {
+//             buf: slice,
+//             byte: 0
+//         }
+//     }
+// }
+
+// impl<'a> OutputBuffer for SliceOutputBuffer<'a> {
+//     #[inline(always)]
+//     fn write(&mut self, value: u8) {
+//         if self.byte < self.buf.len() {
+//             self.buf[self.byte] = value;
+//         }
+//         self.byte += 1;
+//     }
+//     #[inline(always)]
+//     fn write_all(&mut self, slice: &[u8]) {
+//         let sl = slice.len();
+//         let end = self.byte + sl;
+//         if end <= self.buf.len() {
+//             self.buf[self.byte..end].copy_from_slice(slice);
+//         }
+//         self.byte = end;
+//     }
+//     #[inline(always)]
+//     fn pre_alloc(&mut self, _eb: usize) {}
+//     fn copy_back(&mut self, back: usize, mut len: usize) {
+//         if len > back {
+//             while len != 0 {
+//                 let st = self.byte - back;
+//                 OutputBuffer::write_all(self, &self.buf[st..std::cmp::min(st + len as usize, self.byte)]);
+//                 len -= back;
+//             }
+//         } else {
+//             let st = self.byte - back;
+//             OutputBuffer::write_all(self, &self.buf[st..st + len])
+//         }
+//     }
+
+// }
+
+fn inflt(dat: &[u8], buf: &mut dyn OutputBuffer, st: &mut InflateState) -> Result<(), InflateError> {
+    let mut pos = st.pos;
+    let sl = dat.len();
+    if sl == 0 || (st.head && sl < 5) { return Ok(()); }
+    let tbts = sl << 3;
+    let mut clmap = [0u16; 128];
+    let mut le = [0u16; 16];
+    let mut ldt = [0u8; 320];
+    let mut clt = [0u8; 19];
+    loop {
+        if st.head {
+            st.bfinal = bits(dat, pos, 1) != 0;
+            let btype = bits(dat, pos + 1, 3);
+            pos += 3;
+            match btype {
+                0 => {
+                    let s = shft(pos) + 4;
+                    let t = s + (dat[s - 4] as u16 | ((dat[s - 3] as u16) << 8)) as usize;
+                    if t > dat.len() {
+                        if st.last {
+                            return Err(InflateError::UnexpectedEOF);
+                        }
+                        break;
+                    }
+                    buf.write_all(&dat[s..t]);
+                    continue;
+                }
+                1 => {
+                    st.lmap[..512].copy_from_slice(&*flrm);
+                    st.dmap[..32].copy_from_slice(&*fdrm);
+                    st.lbits = 9;
+                    st.dbits = 5;
+                }
+                2 => {
+                    let hlit = bits(dat, pos, 31) as usize + 257;
+                    let hclen = (bits(dat, pos + 10, 15) + 4) as usize;
+                    let tl = hlit + (bits(dat, pos + 5, 31) + 1) as usize;
+                    pos += 14;
+                    for i in 0..hclen {
+                        clt[clim[i]] = bits(dat, pos + (i * 3) as usize, 7);
+                    }
+                    pos += hclen * 3;
+                    for i in hclen..19 {
+                        clt[clim[i]] = 0;
+                    }
+                    let clb = max(&clt);
+                    let clbmsk = (1 << clb) - 1;
+                    if !st.last && pos + tl * (clb + 7) as usize > tbts {
+                        break;
+                    }
+                    hrmap(&clt, clb, &mut clmap, &mut le);
+                    let mut i = 0;
+                    loop {
+                        let r = clmap[bits(dat, pos, clbmsk) as usize];
+                        pos += (r & 15) as usize;
+                        let s = (r >> 4) as u8;
+                        if s < 16 {
+                            ldt[i] = s;
+                            i += 1;
+                        } else {
+                            let mut c = 0;
+                            let mut n = 0;
+                            if s == 16 {
+                                n = 3 + bits(dat, pos, 3);
+                                pos += 2;
+                                c = ldt[i - 1];
+                            }
+                            else if s == 17 {
+                                n = 3 + bits(dat, pos, 7);
+                                pos += 3;
+                            }
+                            else if s == 18 {
+                                n = 11 + bits(dat, pos, 127);
+                                pos += 7;
+                            }
+                            let mut un = n as usize;
+                            i += un;
+                            while un > 0 {
+                                ldt[i - un] = c;
+                                un -= 1;
+                            }
+                        }
+                        if i >= tl {
+                            break;
+                        }
+                    }
+                    let lt = &ldt[0..hlit];
+                    let dt = &ldt[hlit..tl];
+                    st.lbits = max(lt);
+                    st.dbits = max(dt);
+                    hrmap(lt, st.lbits, &mut st.lmap, &mut le);
+                    hrmap(dt, st.dbits, &mut st.dmap, &mut le);
+                }
+                _ => {
+                    return Err(InflateError::InvalidBlockType);
+                }
+            }
+            if pos > tbts {
+                return Err(InflateError::UnexpectedEOF);   
+            }
+        }
+        st.head = false;
+        let lms = (1u16 << st.lbits) - 1;
+        let dms = (1u16 << st.dbits) - 1;
+        let top = tbts - (st.lbits + st.dbits + 18) as usize;
+        while st.last || pos < top {
+            let c = st.lmap[
+                bits16(dat, pos, lms) as usize
+            ];
+            pos += (c & 15) as usize;
+            if c == 0 {
+                return Err(InflateError::InvalidLengthOrLiteral);
+            }
+            let sym = c >> 4;
+            if (sym & 256) == 0 {
+                buf.write(sym as u8);
+            } else if sym == 256 {
+                st.head = true;
+                break;
+            } else {
+                let mut add = sym - 254;
+                if add > 10 {
+                    let i = add as usize - 3;
+                    let b = fleb[i];
+                    add = bits(dat, pos, (1 << b) - 1) as u16 + fl[i];
+                    pos += b;
+                }
+                let d = st.dmap[
+                    bits16(dat, pos, dms) as usize
+                ];
+                if d == 0 {
+                    return Err(InflateError::InvalidDistance);
+                }
+                pos += (d & 15) as usize;
+                let dsym = (d >> 4) as usize;
+                let mut dt = fd[dsym] as usize;
+                if dsym > 3 {
+                    let b = fdeb[dsym];
+                    dt += bits16(dat, pos, (1 << b) - 1) as usize;
+                    pos += b;
+                }
+                if pos > tbts {
+                    return Err(InflateError::UnexpectedEOF);
+                }
+                buf.copy_back(dt, add as usize);
+            }
+        }
+        st.pos = pos;
+        if !st.head || st.bfinal {
+            break;
+        }
+    }
+    Ok(())
+}
+
+pub fn inflate(dat: &[u8], out: &mut dyn OutputBuffer) -> Result<(), InflateError> {
+    let mut st = InflateState::new();
+    st.last = true;
+    inflt(dat, out, &mut st)?;
+    Ok(())
+}

+ 2 - 2
src/index.ts

@@ -673,10 +673,10 @@ type CRCV = {
 
 // CRC32 table
 const crct = /*#__PURE__*/ (() => {
-  const t = new u32(256);
+  const t = new Int32Array(256);
   for (let i = 0; i < 256; ++i) {
     let c = i, k = 9;
-    while (--k) c = ((c & 1) && 0xEDB88320) ^ (c >>> 1);
+    while (--k) c = ((c & 1) && -306674912) ^ (c >>> 1);
     t[i] = c;
   }
   return t;