brotli 0.1.1

A brotli decompressor that runs at comparable speed to the reference C implementation with entirely safe rust code.
Documentation
#[macro_use]
extern crate alloc_no_stdlib as alloc;
extern crate brotli_no_stdlib;
extern crate core;
use std::io;
mod heap_alloc;
mod test;
use heap_alloc::{HeapAllocator};
use brotli_no_stdlib::{HuffmanCode, BrotliState, BrotliDecompressStream, BrotliResult};


pub struct Decompressor<R: io::Read> {
    input_buffer : [u8;65536],
    total_out : usize,
    input_offset : usize,
    input_len : usize,
    input_eof : bool,
    input: R,
    state : BrotliState<HeapAllocator<u8>, HeapAllocator<u32>, HeapAllocator<HuffmanCode> >,
}
macro_rules! stderr {
    ($($arg:tt)*) => (
        use std::io::Write;
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr (file handle closed?): {}", x),
        }
    )
}

impl<R: io::Read> Decompressor<R> {

    pub fn new(r: R) -> Decompressor<R> {
        let ret = Decompressor{
            input_buffer : [0; 65536],
            total_out : 0,
            input_offset : 0,
            input_len : 0,
            input_eof : false,
            input: r,
            state : BrotliState::new(HeapAllocator::<u8>{default_value : 0u8},
                                     HeapAllocator::<u32>{default_value : 0u32},
                                     HeapAllocator::<HuffmanCode>{
                                         default_value : HuffmanCode::default()}),
        };
        return ret;
    }

    pub fn copy_to_front(&mut self) {
        if self.input_offset == self.input_buffer.len() {
            self.input_offset = 0;
            self.input_len = 0;
        } else if self.input_offset + 256 > self.input_buffer.len() {
            let (mut first, second) = self.input_buffer[..].split_at_mut(self.input_offset);
            let avail_in = self.input_len - self.input_offset;
            first[0..avail_in].clone_from_slice(&second[0..avail_in]);
            self.input_offset = 0;
        }
    }
}
impl<'a, R: io::Read> io::Read for Decompressor<R> {
	fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
            let mut output_offset : usize = 0;
            let mut avail_out = buf.len() - output_offset;
            let mut avail_in = self.input_len - self.input_offset;
            let mut needs_input = false;
            while avail_out == buf.len() && (needs_input == false || self.input_eof == false) {
                    if !self.input_eof {
                        match self.input.read(&mut self.input_buffer[self.input_len..]) {
                            Err(e) => match e.kind() {
                                io::ErrorKind::Interrupted => continue,
                                _ => self.input_eof = true,
                            },
                            Ok(size) => if size == 0 {
                                self.input_eof=true;
                            }else {
                                needs_input = false;
                                self.input_len += size;
                                avail_in = self.input_len - self.input_offset;
                            },
                        }
                    }
                    match BrotliDecompressStream(&mut avail_in,
                                                  &mut self.input_offset,
                                                  &self.input_buffer[..],
                                                  &mut avail_out,
                                                  &mut output_offset,
                                                  buf,
                                                  &mut self.total_out,
                                                  &mut self.state) {
                        BrotliResult::NeedsMoreInput => {needs_input = true; self.copy_to_front();},
                        BrotliResult::NeedsMoreOutput => {},
                        BrotliResult::ResultSuccess => break,
                        BrotliResult::ResultFailure => return Err(io::Error::new(io::ErrorKind::InvalidData,
                                                      "Invalid Data")),
                  }
            }
            return Ok(output_offset);
        }
}

pub fn copy_from_to<R:io::Read, W:io::Write>(mut r : R, mut w : W) -> io::Result<usize> {
    let mut buffer : [u8;65536] = [0; 65536];
    let mut out_size : usize = 0;
    loop {
        match r.read(&mut buffer[..]) {
            Err(e) => {
                match e.kind() {
                    io::ErrorKind::Interrupted => continue,
                     _ => {},
                }
                return Err(e)
            },
            Ok(size) => if size == 0 {
               break;
            } else {
                match w.write_all(&buffer[..size]) {
                    Err(e) => {
                        match e.kind() {
                            io::ErrorKind::Interrupted => continue,
                            _ => {},
                        }
                        return Err(e)
                    }
                    Ok(_) => out_size += size,
                }
            },
        }
    }
    return Ok(out_size);
}