Git Product home page Git Product logo

dropbox / rust-brotli Goto Github PK

View Code? Open in Web Editor NEW
785.0 25.0 82.0 13.8 MB

Brotli compressor and decompressor written in rust that optionally avoids the stdlib

Home Page: https://dropbox.tech/infrastructure/-broccoli--syncing-faster-by-syncing-less

License: BSD 3-Clause "New" or "Revised" License

Rust 91.90% Python 0.64% Makefile 0.04% C 3.07% PowerShell 0.01% Shell 0.05% Go 4.24% Just 0.05%
decompression brotli rust brotli-decompressor rustlang safe brotli-compression brotli-encoder brotli-compressor compression

rust-brotli's Introduction

rust-brotli

crates.io Build Status

What's new in 5.0.0

  • The FFI is no longer active by default to avoid ODR issues if multiple versions of brotli are included in several dependent crates.

What's new in 4.0.0

Pinned to a rust-brotli-decompressor that can disable the ffi with the ffi-api flag. This can help avoid symbol conflicts with other brotli libs.

What's new in 3.5

Updated SIMD support. Better CI integration. Cleaned up some of the clippy warnings.

What's new in 3.4

Brotli decompressor's reader and writer has better behavior when operating upon brotli streams with extra bits at the end. Optional features like stdsimd are now tested or disabled for now.

What's new in 3.2

  • into_inner conversions for both Reader and Writer classes

What's new in 3.0

  • A fully compatible FFI for drop-in compatibiltiy with the https://github.com/google/brotli binaries
    • custom allocators fully supported
  • Multithreaded compression so multiple threads can operate in unison on a single file
  • Concatenatability mode to add the feature requested in google/brotli#628
    • binary tool catbrotli can accomplish this if the first file was specified with -apendable and the second with -catable
  • validation mode where a file is double-checked to be able to be decompressed with the same settings; useful for benchmarking or fuzzing
  • Magic Number: where the brotli file can have a useful header with a few magic bytes, concatability info and a final output size for pre-allocating memory

What's new in 2.5

  • In 2.5 The callback also passes down an allocator to make new StaticCommands and PDFs and 256 bit floating point vectors.
  • In 2.4 The callback with the compression intermediate representation now passes a full metablock at a time. Also these items are mutable in case futher optimization is desired

What's new in 2.3

  • Flush now produces output instead of calling finish on the stream. This allows you to use the writer abstraction to get immediate output without having to resort to the CompressStream internal abstraction

Project Requirements

Direct no-stdlib port of the C brotli compressor to Rust

no dependency on the Rust stdlib: this library would be ideal for decompressing within a rust kernel among other things.

This is useful to see how C and Rust compare in an apples-to-apples comparison where the same algorithms and data structures and optimizations are employed.

Compression Usage

Rust brotli currently supports compression levels 0 - 11 They should be bitwise identical to the brotli C compression engine at compression levels 0-9 Recommended lg_window_size is between 20 and 22

With the io::Read abstraction

let mut input = brotli::CompressorReader::new(&mut io::stdin(), 4096 /* buffer size */,
                                              quality as u32, lg_window_size as u32);

then you can simply read input as you would any other io::Read class

With the io::Write abstraction

let mut writer = brotli::Compressor::new(&mut io::stdout(), 4096 /* buffer size */,
                                         quality as u32, lg_window_size as u32);

There are also methods to build Compressor Readers or Writers using the with_params static function

eg:

let params = BrotliEncoderParams::default();
// modify params to fit the application needs
let mut writer = brotli::Compressor::with_params(&mut io::stdout(), 4096 /* buffer size */,
                                         params);

or for the reader

let params = BrotliEncoderParams::default();
// modify params to fit the application needs
let mut writer = brotli::CompressorReader::with_params(&mut io::stdin(), 4096 /* buffer size */,
                                                       params);

With the Stream Copy abstraction

match brotli::BrotliCompress(&mut io::stdin(), &mut io::stdout(), &brotli_encoder_params) {
    Ok(_) => {},
    Err(e) => panic!("Error {:?}", e),
}

Decompression Usage

With the io::Read abstraction

let mut input = brotli::Decompressor::new(&mut io::stdin(), 4096 /* buffer size */);

then you can simply read input as you would any other io::Read class

With the io::Write abstraction

let mut writer = brotli::DecompressorWriter::new(&mut io::stdout(), 4096 /* buffer size */);

With the Stream Copy abstraction

match brotli::BrotliDecompress(&mut io::stdin(), &mut io::stdout()) {
    Ok(_) => {},
    Err(e) => panic!("Error {:?}", e),
}

With manual memory management

There are 3 steps to using brotli without stdlib

  1. setup the memory manager
  2. setup the BrotliState
  3. in a loop, call BrotliDecompressStream

in Detail

// at global scope declare a MemPool type -- in this case we'll choose the heap to
// avoid unsafe code, and avoid restrictions of the stack size

declare_stack_allocator_struct!(MemPool, heap);

// at local scope, make a heap allocated buffers to hold uint8's uint32's and huffman codes
let mut u8_buffer = define_allocator_memory_pool!(4096, u8, [0; 32 * 1024 * 1024], heap);
let mut u32_buffer = define_allocator_memory_pool!(4096, u32, [0; 1024 * 1024], heap);
let mut hc_buffer = define_allocator_memory_pool!(4096, HuffmanCode, [0; 4 * 1024 * 1024], heap);
let heap_u8_allocator = HeapPrealloc::<u8>::new_allocator(4096, &mut u8_buffer, bzero);
let heap_u32_allocator = HeapPrealloc::<u32>::new_allocator(4096, &mut u32_buffer, bzero);
let heap_hc_allocator = HeapPrealloc::<HuffmanCode>::new_allocator(4096, &mut hc_buffer, bzero);

// At this point no more syscalls are going to be needed since everything can come from the allocators.

// Feel free to activate SECCOMP jailing or other mechanisms to secure your application if you wish.

// Now it's possible to setup the decompressor state
let mut brotli_state = BrotliState::new(heap_u8_allocator, heap_u32_allocator, heap_hc_allocator);

// at this point the decompressor simply needs an input and output buffer and the ability to track
// the available data left in each buffer
loop {
    result = BrotliDecompressStream(&mut available_in, &mut input_offset, &input.slice(),
                                    &mut available_out, &mut output_offset, &mut output.slice_mut(),
                                    &mut written, &mut brotli_state);

    // just end the decompression if result is BrotliResult::ResultSuccess or BrotliResult::ResultFailure
}

This interface is the same interface that the C brotli decompressor uses

Also feel free to use custom allocators that invoke Box directly. This example illustrates a mechanism to avoid subsequent syscalls after the initial allocation

Using the C interface

rust-brotli is a drop-in replacement for the official https://github.com/google/brotli C implementation. That means you can use it from any place that supports that library. To build rust-brotli in this manner enter the c subdirectory and run make there

cd c && make

this should build c/target/release/libbrotli.so and should build the vanilla command line tool in C for compressing and decompressing any brotli file.

the libbrotli.so in c/target/release should be able to replace any other libbrotli.so file, but with all the advantages of using safe rust (except in the FFI bindings)

The code also allows a wider range of options, including forcing the prediction mode (eg UTF8 vs signed vs MSB vs LSB) and changing the weight of the literal cost from 540 to other values.

Additionally the CATABLE and APPENDABLE options are exposed and allow concatenation of files created in this manner.

Specifically CATABLE files can be concatenated in any order using the catbrotli tool and APPENDABLE files can be the first file in a sequence of catable files... eg you can combine appendable.br catable1.br catable2.br catable3.br

or simply catable0.br catable1.br catable2.br catable3.br

rust-brotli's People

Contributors

alexanderkjall avatar atouchet avatar billyb2 avatar danielrh avatar dependabot[bot] avatar durin42 avatar joliss avatar killercup avatar lesniewski avatar llogiq avatar manonthemat avatar martin1887 avatar miwig avatar mtth-bfft avatar nemo157 avatar nyurik avatar object905 avatar philippeitis avatar programingjd avatar robjtede avatar yoric avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-brotli's Issues

impl Default for BrotliEncoderParams and documentation of the parameters

Hello.

I'm using this library and I have noticed that the struct BrotliEncoderParams has many and not documented fields.

It would nice having a new method or a Default implementation for this struct with sane defaults.

For instance, quality 1 and lgwin 22 are the values I am using, and they provide a fast compression with the recommended value for the window size. There are many other attributes and I am slightly lost however.

Updating the README should be also desirable, since the BrotliCompress method receives quality and lgwin as parameters instead BrotliEncoderParams in the README. I have noticed it because a compilation error, and I have needed navigating into the source code to find the correct BrotliCompress signature.

Thanks and regards.

Publish new version

Could we get a new version on crates.io now that the simd feature is working again ?
I don't really like pointing to a git ref directly.

Size of published crate could be smaller

src/bin/testdata is over 18MB and entirely useless in the published crate since people don't get crates off of crates.io in order to run its tests.
I also found no references to the corrosion folder in the source code, which leads me to think it is also dead weight taking up another 26MB of space which isn't needed in the published crate.
Granted the actual space taken up in the .crate that people download from crates.io is less due to compression, but that's still quite a lot of savings.

Code should check that buffer-length is not 0

After a few hours of debugging, I finally realized that I had accidentally passed a buffer length of 0 to the API. For some reason, this doesn't work :)

Since 0 is obviously not a valid value, could the code add an assertion to ensure that it's not 0?

Multiple panics caused by malformed inputs

Multiple runtime panics can be triggerred by constructing malformed data structures or function arguments. I believe the API design can be improve the get rid of these problems.

Examples:

use brotli::enc::command::BrotliDistanceParams;
use brotli::enc::command::Command;

fn main() {
    let mut command = Command::default();
    command.dist_prefix_ = 1000;
    let params = BrotliDistanceParams {
        distance_postfix_bits: 40,
        num_direct_distance_codes: 0,
        alphabet_size: 0,
        max_distance: 0,
    };
    let _ = brotli::enc::command::CommandRestoreDistanceCode(&command, &params);
}
use brotli::enc::command::PrefixEncodeCopyDistance;

fn main() {
    let mut code = 0;
    let mut extra_bits = 0;
    PrefixEncodeCopyDistance(100, 0, 100, &mut code, &mut extra_bits);
}
use brotli::enc::brotli_bit_stream::BrotliBuildAndStoreHuffmanTreeFast;
use brotli::enc::writer::StandardAlloc;
fn main() {
    let mut alloc = StandardAlloc::default();
    BrotliBuildAndStoreHuffmanTreeFast(
        &mut alloc,
        &[0],
        0,
        0,
        &mut [0],
        &mut [0],
        &mut 99999,
        &mut [0],
    );
}

integration tests in src/bin/ run forever with `--features='seccomp'`

This may not be important, but it looks a bit spicy:

     Running target/debug/deps/brotli-69525ecfc53fa34c

running 93 tests
1 Iterations; Time 0.002088729
test integration_tests::test_10x_10y_one_out_byte ... ok
1 Iterations; Time 0.002077081
test integration_tests::test_10x_10y_byte_by_byte ... ok

thread 'integration_tests::test_10x_10y' has overflowed its stack
fatal runtime error: stack overflow

thread 'integration_tests::test_64x' has overflowed its stack
fatal runtime error: stack overflow
1 Iterations; Time 0.625489011
test integration_tests::test_alice1 ... ok

thread 'integration_tests::test_alice29' has overflowed its stack
fatal runtime error: stack overflow

thread 'integration_tests::test_1024k' has overflowed its stack
fatal runtime error: stack overflow
test integration_tests::test_1024k ... test integration_tests::test_1024k has been running for over 60 seconds
test integration_tests::test_10x_10y ... test integration_tests::test_10x_10y has been running for over 60 seconds
test integration_tests::test_64x ... test integration_tests::test_64x has been running for over 60 seconds
test integration_tests::test_alice29 ... test integration_tests::test_alice29 has been running for over 60

Poking at the instance with strace shows one process waiting with

futex(5fe7288da9c, FUTEX_WAIT_PRIVATE, 0, NULL

And its parent is doing

wait4(17733,

So there seems to be some sort of thread mess happening.

And annoyingly, when you invoke the program with

 target/debug/deps/brotli-69525ecfc53fa34c --test-threads 1

It panics after printing:


running 93 tests
test integration_tests::test_1024k ... 

And you get a nice notice in dmesg:

[3552418.530377] audit: type=1326 audit(1582361087.220:47): auid=1000 uid=1000 gid=1000 ses=2 pid=17945 comm="integration_tes" exe="/tmp/rust-brotli/target/debug/deps/brotli-69525ecfc53fa34c" sig=9 arch=c000003e syscall=202 compat=0 ip=0x7fcbea49a60a code=0x0

Running with strace and --test-threads=2 gives this:

strace -f target/debug/deps/brotli-2390a973bcc44b8e --test-threads=2
execve("target/debug/deps/brotli-2390a973bcc44b8e", ["target/debug/deps/brotli-2390a97"..., "--test-threads", "2"], 0x7ffe89314108 /* 112 vars */) = 0
brk(NULL)                               = 0x55e6e8892000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=369771, ...}) = 0
mmap(NULL, 369771, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9088bc4000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\21\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=18520, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088bc2000
mmap(NULL, 20752, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9088bbc000
mmap(0x7f9088bbd000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x7f9088bbd000
mmap(0x7f9088bbf000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f9088bbf000
mmap(0x7f9088bc0000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f9088bc0000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0pm\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2788552, ...}) = 0
mmap(NULL, 140448, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9088b99000
mmap(0x7f9088b9f000, 73728, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f9088b9f000
mmap(0x7f9088bb1000, 20480, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7f9088bb1000
mmap(0x7f9088bb6000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c000) = 0x7f9088bb6000
mmap(0x7f9088bb8000, 13472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f9088bb8000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0203\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=100624, ...}) = 0
mmap(NULL, 103504, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9088b7f000
mmap(0x7f9088b82000, 69632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f9088b82000
mmap(0x7f9088b93000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14000) = 0x7f9088b93000
mmap(0x7f9088b97000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7f9088b97000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000@\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1889072, ...}) = 0
mmap(NULL, 1902152, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f90889ae000
mmap(0x7f90889d0000, 1417216, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f90889d0000
mmap(0x7f9088b2a000, 307200, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17c000) = 0x7f9088b2a000
mmap(0x7f9088b75000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c6000) = 0x7f9088b75000
mmap(0x7f9088b7b000, 13896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f9088b7b000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\321\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1321152, ...}) = 0
mmap(NULL, 1323264, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f908886a000
mmap(0x7f9088877000, 638976, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x7f9088877000
mmap(0x7f9088913000, 626688, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xa9000) = 0x7f9088913000
mmap(0x7f90889ac000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x141000) = 0x7f90889ac000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088868000
arch_prctl(ARCH_SET_FS, 0x7f9088869380) = 0
mprotect(0x7f9088b75000, 16384, PROT_READ) = 0
mprotect(0x7f90889ac000, 4096, PROT_READ) = 0
mprotect(0x7f9088b97000, 4096, PROT_READ) = 0
mprotect(0x7f9088bb6000, 4096, PROT_READ) = 0
mprotect(0x7f9088bc0000, 4096, PROT_READ) = 0
mprotect(0x55e6e8218000, 135168, PROT_READ) = 0
mprotect(0x7f9088c47000, 4096, PROT_READ) = 0
munmap(0x7f9088bc4000, 369771)          = 0
set_tid_address(0x7f9088869650)         = 19338
set_robust_list(0x7f9088869660, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7f9088b9f6e0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f9088bae2f0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7f9088b9f7b0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f9088bae2f0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f90889e81d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
brk(NULL)                               = 0x55e6e8892000
brk(0x55e6e88b3000)                     = 0x55e6e88b3000
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "55e6e7a3c000-55e6e7a68000 r--p 0"..., 1024) = 1024
read(3, "0010                    /lib64/l"..., 1024) = 1024
read(3, "-p 00014000 08:06 5922514       "..., 1024) = 1024
read(3, "000 08:06 5858076               "..., 1024) = 1024
close(3)                                = 0
sched_getaffinity(19338, 32, [0, 1, 2, 3]) = 8
rt_sigaction(SIGSEGV, {sa_handler=0x55e6e7e37530, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7f9088bae2f0}, NULL, 8) = 0
rt_sigaction(SIGBUS, {sa_handler=0x55e6e7e37530, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7f9088bae2f0}, NULL, 8) = 0
sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088c1d000
sigaltstack({ss_sp=0x7f9088c1d000, ss_flags=0, ss_size=8192}, NULL) = 0
statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address)
statx(AT_FDCWD, "/home/kent/.terminfo", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7ffd282a5eb0) = -1 ENOENT (No such file or directory)
statx(AT_FDCWD, "/etc/terminfo", AT_STATX_SYNC_AS_STAT, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=0, stx_mode=S_IFDIR|0755, stx_size=4096, ...}) = 0
statx(AT_FDCWD, "/etc/terminfo/r/rxvt-unicode-256color", AT_STATX_SYNC_AS_STAT, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=2226, ...}) = 0
openat(AT_FDCWD, "/etc/terminfo/r/rxvt-unicode-256color", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
read(3, "\32\1N\0\35\0\37\0p\1\34\5rxvt-unicode-256colo"..., 8192) = 2226
getrandom("\x22\x9c\x93\x1c\x7c\x62\xb3\xbc\xfb\x93\x70\xae\x48\x87\xb9\xe0", 16, GRND_NONBLOCK) = 16
close(3)                                = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, "\nrunning 82 tests\n", 18
running 82 tests
)    = 18
futex(0x7f9088bc10c8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
mmap(NULL, 2101248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f9088667000
mprotect(0x7f9088668000, 2097152, PROT_READ|PROT_WRITE) = 0
clone(child_stack=0x7f9088866eb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 19339 attached
, parent_tid=[19339], tls=0x7f9088867700, child_tidptr=0x7f90888679d0) = 19339
[pid 19339] set_robust_list(0x7f90888679e0, 24 <unfinished ...>
[pid 19338] mmap(NULL, 2101248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0 <unfinished ...>
[pid 19339] <... set_robust_list resumed>) = 0
[pid 19338] <... mmap resumed>)         = 0x7f9088466000
[pid 19339] sigaltstack(NULL,  <unfinished ...>
[pid 19338] mprotect(0x7f9088467000, 2097152, PROT_READ|PROT_WRITE <unfinished ...>
[pid 19339] <... sigaltstack resumed>{ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
[pid 19338] <... mprotect resumed>)     = 0
[pid 19339] mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid 19338] clone(child_stack=0x7f9088665eb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID <unfinished ...>
[pid 19339] <... mmap resumed>)         = 0x7f9088c1b000
strace: Process 19340 attached
[pid 19339] sigaltstack({ss_sp=0x7f9088c1b000, ss_flags=0, ss_size=8192},  <unfinished ...>
[pid 19338] <... clone resumed>, parent_tid=[19340], tls=0x7f9088666700, child_tidptr=0x7f90886669d0) = 19340
[pid 19340] set_robust_list(0x7f90886669e0, 24 <unfinished ...>
[pid 19338] futex(0x55e6e8892a98, FUTEX_WAIT_BITSET_PRIVATE, 0, {tv_sec=3553292, tv_nsec=858960840}, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 19339] <... sigaltstack resumed>NULL) = 0
[pid 19340] <... set_robust_list resumed>) = 0
[pid 19339] prctl(PR_SET_NAME, "integration_tes"... <unfinished ...>
[pid 19340] sigaltstack(NULL,  <unfinished ...>
[pid 19339] <... prctl resumed>)        = 0
[pid 19340] <... sigaltstack resumed>{ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
[pid 19340] mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid 19339] mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7f9080466000
[pid 19340] <... mmap resumed>)         = 0x7f9088c19000
[pid 19339] munmap(0x7f9080466000, 62496768 <unfinished ...>
[pid 19340] sigaltstack({ss_sp=0x7f9088c19000, ss_flags=0, ss_size=8192},  <unfinished ...>
[pid 19339] <... munmap resumed>)       = 0
[pid 19340] <... sigaltstack resumed>NULL) = 0
[pid 19339] munmap(0x7f9088000000, 4612096 <unfinished ...>
[pid 19340] prctl(PR_SET_NAME, "integration_tes"... <unfinished ...>
[pid 19339] <... munmap resumed>)       = 0
[pid 19340] <... prctl resumed>)        = 0
[pid 19339] mprotect(0x7f9084000000, 135168, PROT_READ|PROT_WRITE) = 0
[pid 19340] mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0 <unfinished ...>
[pid 19339] sched_getaffinity(19339, 32,  <unfinished ...>
[pid 19340] <... mmap resumed>)         = 0x7f907c000000
[pid 19339] <... sched_getaffinity resumed>[0, 1, 2, 3]) = 8
[pid 19340] munmap(0x7f9080000000, 67108864 <unfinished ...>
[pid 19339] mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid 19340] <... munmap resumed>)       = 0
[pid 19339] <... mmap resumed>)         = 0x7f9088365000
[pid 19340] mprotect(0x7f907c000000, 135168, PROT_READ|PROT_WRITE) = 0
[pid 19340] sched_getaffinity(19340, 32, [0, 1, 2, 3]) = 8
[pid 19340] mmap(NULL, 209719296, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f906f7ff000
[pid 19340] mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f906b7fe000
[pid 19340] prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) = 0
[pid 19340] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x7f90884668c8} ---
[pid 19340] write(2, "\nthread '", 9
thread ')   = 9
[pid 19340] write(2, "integration_tests::test_10x_10y", 31integration_tests::test_10x_10y) = 31
[pid 19340] write(2, "' has overflowed its stack\n", 27' has overflowed its stack
) = 27
[pid 19340] write(2, "fatal runtime error: ", 21fatal runtime error: ) = 21
[pid 19340] write(2, "stack overflow", 14stack overflow) = 14
[pid 19340] write(2, "\n", 1
)           = 1
[pid 19340] rt_sigprocmask(SIG_UNBLOCK, [ABRT],  <unfinished ...>) = ?
[pid 19340] +++ killed by SIGKILL +++
[pid 19339] mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088264000
[pid 19339] mmap(NULL, 1060864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088161000
[pid 19339] mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088060000
[pid 19339] mmap(NULL, 8409088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f90837fb000
[pid 19339] mprotect(0x7f9084021000, 32768, PROT_READ|PROT_WRITE) = 0
[pid 19339] mmap(NULL, 200704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9088be8000
[pid 19339] mmap(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f908801f000
[pid 19339] mprotect(0x7f9084029000, 4096, PROT_READ|PROT_WRITE) = 0
[pid 19339] mprotect(0x7f908402a000, 8192, PROT_READ|PROT_WRITE) = 0
[pid 19339] mprotect(0x7f908402c000, 57344, PROT_READ|PROT_WRITE) = 0
[pid 19339] munmap(0x7f9088be8000, 200704) = 0
[pid 19339] munmap(0x7f90837fb000, 8409088) = 0
[pid 19339] munmap(0x7f908801f000, 266240) = 0
[pid 19339] mmap(NULL, 209719296, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f905effd000
[pid 19339] mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f905affc000
[pid 19339] prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) = 0
[pid 19339] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x7f9088667628} ---
[pid 19339] write(2, "\nthread '", 9
thread ')   = 9
[pid 19339] write(2, "integration_tests::test_1024k", 29integration_tests::test_1024k) = 29
[pid 19339] write(2, "' has overflowed its stack\n", 27' has overflowed its stack
) = 27
[pid 19339] write(2, "fatal runtime error: ", 21fatal runtime error: ) = 21
[pid 19339] write(2, "stack overflow", 14stack overflow) = 14
[pid 19339] write(2, "\n", 1
)           = 1
[pid 19339] futex(0x7f9088b7ac50, FUTEX_WAIT_PRIVATE, 2, NULL) = ?
[pid 19339] +++ killed by SIGKILL +++

Failing binary attached

brotli-2390a973bcc44b8e.gz

corrupt stream with extra bytes is not rejected

Steps to reproduce:

Read a Brotli stream with extra junk at the end.

Expected result:

Receive an Err from brotli_decompressor::Decompressor::read.

Actual result:

No error.

For comparison, the brotli command line tool rejects streams with extra junk at the end:

$ (brotli -c <<<"hello"; echo goodbye) > corrupt.br
$ brotli -d < corrupt.br
hello
corrupt input [con]
$ echo $?
1

Test code to reproduce:

    #[test]
    fn test_no_leftovers() {
        // Output from this command:
        // (brotli -c <<<"hello"; echo goodbye) | xxd -p | sed 's/../\\x&/g'
        let compressed_with_extra = b"\x8f\x02\x80\x68\x65\x6c\x6c\x6f\x0a\x03\x67\x6f\x6f\x64\x62\x79\x65\x0a";
        let mut reader = brotli_decompressor::Decompressor::new(Cursor::new(compressed_with_extra), 8000);
        assert!(std::io::read_to_string(&mut reader).is_err());
    }

Add a helper for compressing a slice into a vec

A common use case is compressing a &[u8] into a Vec<u8> without doing any I/O. The current docs don't make it clear how to do this.

A google search turns up this forum post with this code snippet:

use std::io::Write;

pub fn compress(input: &[u8]) -> Vec<u8> {
    let mut writer = brotli::CompressorWriter::new(
        Vec::new(),
        4096,
        11,
        22);
    writer.write_all(input).unwrap();
    writer.into_inner()
}

Which is nontrivial to figure out. A helper functions in the root of the crate to compress a &[u8] into a Vec<u8> and to decompress a Vec<u8> into a &[u8] would help a lot with this. (Also, if these functions don't do I/O then perhaps they could be be infallible.)

BrotliEncoderCompressStream with empty output causes BrotliEncoderTakeOutput to panic

It is a bit not clear whether encoder has own internal buffer like C library.
This panic happens when I feed empty next_out_array slice, and want to use BrotliEncoderTakeOutput result to write data without using own temporarely storage.

So just wanted to clarify if BrotliEncoderCompressStream can be used with empty next_out_array

P.s. it also seem to happen only when I push multiple chunks

Changing the default quality level

At the moment the default quality level when encoding is 11, when using BrotliEncoderParams::default(), see source.

I was wondering if there is any interest in changing the default to something more reasonable, as 11 is the highest and takes an extremely long time.

Clippy has some suggestions

clippy has some suggestions. And when I say 'some', I meant 'a lot' :)

While a lot are stylistic (unneeded return mostly), some are actually helpful, e.g.,

  • using .enumerate() instead of incrementing an index (might actually be optimised in another way),
  • calling .clone() on a Copy type,
  • unneeded lifetime parameters,
  • unneeded (mutable) borrows (that are immediately dereferenced or do not need to be mutable)
  • collapsible ifs

Let me just paste the results here

   Compiling brotli v1.0.6 (file:///Users/pascal/Projekte/tools/rust-brotli)
warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:45:5
   |>
45 |>     return BrotliBitReader {
   |>     ^
help: remove `return` as shown:
src/bit_reader/mod.rs:       BrotliBitReader {
src/bit_reader/mod.rs:         val_: 0,
src/bit_reader/mod.rs:         bit_pos_: 0,
src/bit_reader/mod.rs:         next_in: 0,
src/bit_reader/mod.rs:         avail_in: 0,
src/bit_reader/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:63:5
   |>
63 |>     return BrotliBitReaderState {
   |>     ^
help: remove `return` as shown:
src/bit_reader/mod.rs:       BrotliBitReaderState {
src/bit_reader/mod.rs:         val_: 0,
src/bit_reader/mod.rs:         bit_pos_: 0,
src/bit_reader/mod.rs:         next_in: 0,
src/bit_reader/mod.rs:         avail_in: 0,
src/bit_reader/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:74:3
   |>
74 |>   return BrotliBitReaderState {
   |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:     BrotliBitReaderState {
src/bit_reader/mod.rs:       val_: from.val_,
src/bit_reader/mod.rs:       bit_pos_: from.bit_pos_,
src/bit_reader/mod.rs:       next_in: from.next_in,
src/bit_reader/mod.rs:       avail_in: from.avail_in,
src/bit_reader/mod.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:90:3
   |>
90 |>   return ((::core::mem::size_of::() as u32) << 3) - br.bit_pos_;
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:     ((::core::mem::size_of::() as u32) << 3) - br.bit_pos_
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:96:3
   |>
96 |>   return br.avail_in + (BrotliGetAvailableBits(br) >> 3);
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:     br.avail_in + (BrotliGetAvailableBits(br) >> 3)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:102:3
    |>
102 |>   return br.avail_in >= num;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      br.avail_in >= num
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:109:3
    |>
109 |>   return (fast!((input)[next_in]) as u16) | ((fast!((input)[next_in + 1]) as u16) << 8);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (fast!((input)[next_in]) as u16) | ((fast!((input)[next_in + 1]) as u16) << 8)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:118:3
    |>
118 |>   return (four_byte[0] as u32) | ((four_byte[1] as u32) << 8) | ((four_byte[2] as u32) << 16) |
    |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (four_byte[0] as u32) | ((four_byte[1] as u32) << 8) | ((four_byte[2] as u32) << 16) |
src/bit_reader/mod.rs:             ((four_byte[3] as u32) << 24)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:127:3
    |>
127 |>   return (eight_byte[0] as u64) | ((eight_byte[1] as u64) << 8) | ((eight_byte[2] as u64) << 16) |
    |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (eight_byte[0] as u64) | ((eight_byte[1] as u64) << 8) | ((eight_byte[2] as u64) << 16) |
src/bit_reader/mod.rs:             ((eight_byte[3] as u64) << 24) |
src/bit_reader/mod.rs:             ((eight_byte[4] as u64) << 32) | ((eight_byte[5] as u64) << 40) |
src/bit_reader/mod.rs:             ((eight_byte[6] as u64) << 48) | ((eight_byte[7] as u64) << 56)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:255:3
    |>
255 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:262:3
    |>
262 |>   return br.val_ >> br.bit_pos_;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      br.val_ >> br.bit_pos_
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:270:3
    |>
270 |>   return (BrotliGetBitsUnmasked(br) & (0xffffffffu32 as reg_t)) as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) & (0xffffffffu32 as reg_t)) as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:276:3
    |>
276 |>   return (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:283:3
    |>
283 |>   return (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:299:3
    |>
299 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:341:5
    |>
341 |>     return val;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        val
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:349:5
    |>
349 |>     return low_val | (high_val << 16);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        low_val | (high_val << 16)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:361:5
    |>
361 |>     return val;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        val
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:369:5
    |>
369 |>     return low_val | (high_val << 16);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        low_val | (high_val << 16)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:386:3
    |>
386 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:397:3
    |>
397 |>   return pad_bits == 0;
    |>   ^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      pad_bits == 0
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:414:3
    |>
414 |>   return -1;
    |>   ^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      -1
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:459:3
    |>
459 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:34:5
   |>
34 |>     return self.value == other.value && self.bits == other.bits;
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:       self.value == other.value && self.bits == other.bits
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:40:5
   |>
40 |>     return HuffmanCode {
   |>     ^
help: remove `return` as shown:
src/huffman/mod.rs:       HuffmanCode {
src/huffman/mod.rs:         value: 0,
src/huffman/mod.rs:         bits: 0,
src/huffman/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:79:9
   |>
79 |>         return fast_mut!((self.codes.slice_mut())[start;]);
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:           &mut $slice[$start..]
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:84:9
   |>
84 |>         return & fast_slice!((self.codes)[start;]);
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:           & fast_slice!((self.codes)[start;])
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:107:7
    |>
107 |>       return ret;
    |>       ^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:          ret
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:114:9
    |>
114 |>         return HuffmanTreeGroup:: {
    |>         ^
help: remove `return` as shown:
src/huffman/mod.rs:            HuffmanTreeGroup:: {
src/huffman/mod.rs:                htrees : AllocU32::AllocatedMemory::default(),
src/huffman/mod.rs:                codes : AllocHC::AllocatedMemory::default(),
src/huffman/mod.rs:                alphabet_size : 0,
src/huffman/mod.rs:                num_htrees : 0,
src/huffman/mod.rs:            }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:153:3
    |>
153 |>   return fast!((kReverseBits)[num as usize]) as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      fast!((kReverseBits)[num as usize]) as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:185:3
    |>
185 |>   return len - root_bits;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      len - root_bits
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:378:3
    |>
378 |>   return total_size as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      total_size as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:472:3
    |>
472 |>   return goal_size;
    |>   ^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      goal_size
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:336:9
    |>
336 |>         return retval;
    |>         ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:            retval
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:400:17
    |>
400 |>                 return BrotliGetAvailableBits(&self.br) == 0,
    |>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                    BrotliGetAvailableBits(&self.br) == 0,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:401:18
    |>
401 |>             _ => return false,
    |>                  ^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                _ => false,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:407:54
    |>
407 |>             BrotliRunningState::BROTLI_STATE_DONE => return true,
    |>                                                      ^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                BrotliRunningState::BROTLI_STATE_DONE => true,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:408:18
    |>
408 |>             _ => return false,
    |>                  ^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                _ => false,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/transform.rs:734:3
    |>
734 |>   return 3;
    |>   ^^^^^^^^^
help: remove `return` as shown:
src/transform.rs:      3
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/transform.rs:794:5
    |>
794 |>     return idx;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/transform.rs:        idx
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/decode.rs:74:3
   |>
74 |>   return BrotliResult::ResultFailure;
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:     BrotliResult::ResultFailure
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:110:3
    |>
110 |>   return 17;
    |>   ^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      17
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:314:3
    |>
314 |>   return table_element.value as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      table_element.value as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:321:3
    |>
321 |>   return DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:364:3
    |>
364 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:379:3
    |>
379 |>   return SafeDecodeSymbol(&table, br, result);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      SafeDecodeSymbol(&table, br, result)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:421:3
    |>
421 |>   return result;
    |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:430:3
    |>
430 |>   return result;
    |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:479:3
    |>
479 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:646:3
    |>
646 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:713:3
    |>
713 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:770:3
    |>
770 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:947:3
    |>
947 |>   return fast_ref!((prefix::kBlockLengthPrefixCode)[code as usize]).offset as u32 +
    |>   ^
help: remove `return` as shown:
src/decode.rs:      fast_ref!((prefix::kBlockLengthPrefixCode)[code as usize]).offset as u32 +
src/decode.rs:             bit_reader::BrotliReadBits(br, nbits, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:966:7
    |>
966 |>       return (true, index);
    |>       ^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:          (true, index)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:968:10
    |>
968 |>     _ => return (true, block_length_index),
    |>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:        _ => (true, block_length_index),
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:992:3
    |>
992 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1139:3
     |>
1139 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1354:3
     |>
1354 |>   return retval;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       retval
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1410:3
     |>
1410 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1439:3
     |>
1439 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1473:3
     |>
1473 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1493:3
     |>
1493 |>   return DecodeCommandBlockSwitchInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       DecodeCommandBlockSwitchInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1513:3
     |>
1513 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1534:3
     |>
1534 |>   return DecodeDistanceBlockSwitchInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       DecodeDistanceBlockSwitchInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1575:3
     |>
1575 |>   return BrotliResult::ResultSuccess;
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1691:3
     |>
1691 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1720:3
     |>
1720 |>   return BrotliResult::ResultSuccess;
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1763:5
     |>
1763 |>     return bit_reader::BrotliSafeReadBits(br, n_bits, val, input);
     |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:         bit_reader::BrotliSafeReadBits(br, n_bits, val, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1766:5
     |>
1766 |>     return true;
     |>     ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:         true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1837:3
     |>
1837 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1898:3
     |>
1898 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1906:3
     |>
1906 |>   return bit_reader::BrotliWarmupBitReader(br, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       bit_reader::BrotliWarmupBitReader(br, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1913:3
     |>
1913 |>   return bit_reader::BrotliCheckInputAmount(br, num);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       bit_reader::BrotliCheckInputAmount(br, num)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2331:3
     |>
2331 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2341:3
     |>
2341 |>   return ProcessCommandsInternal(false, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       ProcessCommandsInternal(false, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2351:3
     |>
2351 |>   return ProcessCommandsInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       ProcessCommandsInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2908:3
     |>
2908 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/lib.rs:67:3
   |>
67 |>   return BrotliDecompressCustomAlloc(r,
   |>   ^
help: remove `return` as shown:
src/lib.rs:     BrotliDecompressCustomAlloc(r,
src/lib.rs:                                        w,
src/lib.rs:                                        &mut input_buffer[..],
src/lib.rs:                                        &mut output_buffer[..],
src/lib.rs:                                        HeapAlloc:: { default_value: 0 },
src/lib.rs:                                        HeapAlloc:: { default_value: 0 },
              ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:114:3
    |>
114 |>   return BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
    |>   ^
help: remove `return` as shown:
src/lib.rs:      BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
src/lib.rs:                                      &mut IoWriterWrapper::(w),
src/lib.rs:                                      input_buffer,
src/lib.rs:                                      output_buffer,
src/lib.rs:                                      alloc_u8,
src/lib.rs:                                      alloc_u32,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:238:9
    |>
238 |>         return DecompressorCustomAlloc::(
    |>         ^
help: remove `return` as shown:
src/lib.rs:            DecompressorCustomAlloc::(
src/lib.rs:              DecompressorCustomIo::,
src/lib.rs:                                     BufferType,
src/lib.rs:                                     AllocU8, AllocU32, AllocHC>::new(IntoIoReader::(r),
src/lib.rs:                                                                      buffer,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:260:8
    |>
260 |>        return self.0.read(buf);
    |>        ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:           self.0.read(buf)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:281:5
    |>
281 |>     return Decompressor::(DecompressorCustomAlloc::     ^
help: remove `return` as shown:
src/lib.rs:        Decompressor::(DecompressorCustomAlloc::
src/lib.rs:                                                            as Allocator>::AllocatedMemory,
src/lib.rs:                                                           HeapAlloc,
src/lib.rs:                                                           HeapAlloc,
src/lib.rs:                                                           HeapAlloc >::new(r,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:325:5
    |>
325 |>     return self.0.read(buf);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:        self.0.read(buf)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:372:9
    |>
372 |>         return ret;
    |>         ^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:            ret
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:441:7
    |>
441 |>       return Ok(output_offset);
    |>       ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:          Ok(output_offset)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:476:3
    |>
476 |>   return Ok(out_size);
    |>   ^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:      Ok(out_size)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: you have declared `#[inline(always)]` on `BrotliLoad16LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:106:1
    |>
106 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliLoad32LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:113:1
    |>
113 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliLoad64LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:122:1
    |>
122 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliFillBitWindow`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:134:1
    |>
134 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:160:10
    |>
160 |>   } else {
    |>          ^
help: try
src/bit_reader/mod.rs:      } else if (BROTLI_ALIGNED_READ == 0 && (n_bits <= 8)) {
src/bit_reader/mod.rs:      if (br.bit_pos_ >= 24) {
src/bit_reader/mod.rs:        br.val_ >>= 24;
src/bit_reader/mod.rs:        br.bit_pos_ ^= 24;  // here same as -= 24 because of the if condition
src/bit_reader/mod.rs:        br.val_ |= (BrotliLoad32LE(input, br.next_in) << 8) as u64;
src/bit_reader/mod.rs:        br.avail_in -= 3;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:169:12
    |>
169 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 16 {
src/bit_reader/mod.rs:      br.val_ >>= 16;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 16;  /* here same as -= 16 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad16LE(input, br.next_in) as reg_t) << 16;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `BrotliFillBitWindowCompileTimeNbits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:181:1
    |>
181 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:211:10
    |>
211 |>   } else {
    |>          ^
help: try
src/bit_reader/mod.rs:      } else if
src/bit_reader/mod.rs:    // BROTLI_ALIGNED_READ == false &&
src/bit_reader/mod.rs:    n_bits <= 8 {
src/bit_reader/mod.rs:      // !BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {
src/bit_reader/mod.rs:      if br.bit_pos_ >= 24 {
src/bit_reader/mod.rs:        br.val_ >>= 24;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:202:12
    |>
202 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 32 {
src/bit_reader/mod.rs:      br.val_ >>= 32;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 32;  /* here same as -= 32 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad32LE(input, br.next_in) as reg_t) << 32;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:223:12
    |>
223 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 16 {
src/bit_reader/mod.rs:      br.val_ >>= 16;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 16;  /* here same as -= 16 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad16LE(input, br.next_in) as reg_t) << 16;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `BrotliGetBitsUnmasked`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:260:1
    |>
260 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliGet16BitsUnmasked`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:267:1
    |>
267 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliDropBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:303:1
    |>
303 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliTakeBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:323:1
    |>
323 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliReadBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:335:1
    |>
335 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:446:3
    |>
446 |>   if BrotliGetAvailableBits(br) == 0 {
    |>   ^
help: try
src/bit_reader/mod.rs:      if BrotliGetAvailableBits(br) == 0 && (!BrotliPullByte(br, input)) {
src/bit_reader/mod.rs:      return false;
src/bit_reader/mod.rs:    }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: defining a method called `eq` on this type; consider implementing the `std::cmp::PartialEq` trait or choosing a less ambiguous name, #[warn(should_implement_trait)] on by default
  --> src/huffman/mod.rs:33:3
   |>
33 |>   pub fn eq(&self, other: &Self) -> bool {
   |>   ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
  --> src/huffman/mod.rs:77:5
   |>
77 |>     pub fn get_tree_mut<'a>(self :&'a mut Self, index : u32) -> &'a mut [HuffmanCode] {
   |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
  --> src/huffman/mod.rs:82:5
   |>
82 |>     pub fn get_tree<'a>(self :&'a Self, index : u32) -> &'a [HuffmanCode] {
   |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
  --> src/huffman/mod.rs:84:16
   |>
84 |>         return & fast_slice!((self.codes)[start;]);
   |>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
   --> src/huffman/mod.rs:100:5
    |>
100 |>     pub fn build_hgroup_cache<'a>(self : &'a Self) -> [&'a [HuffmanCode]; 256] {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: the variable `index` is used as a loop counter. Consider using `for (index, item) in self.htrees.slice().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
   --> src/huffman/mod.rs:103:7
    |>
103 |>       for htree in self.htrees.slice() {
    |>       ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/huffman/mod.rs:421:5
    |>
421 |>     let last: u16;
    |>     ^
help: it is more idiomatic to write
src/huffman/mod.rs:        let last = if val.len() > 3 { ($slice)[$index] } else { 65535 };
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: the loop variable `i` is used to index `mval`. Consider using `for (i, item) in mval.iter().enumerate().take(3)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:428:5
    |>
428 |>     for i in 0..3 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: the loop variable `k` is only used to index `mval`. Consider using `for item in mval.iter().take(4).skip(i + 1)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:429:7
    |>
429 |>       for k in i + 1..4 {
    |>       ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: this looks like you are swapping elements of `mval` manually, #[warn(manual_swap)] on by default
   --> src/huffman/mod.rs:431:11
    |>
431 |>           let t: u16 = mval[k];
    |>           ^
help: try
src/huffman/mod.rs:              mval.swap(k, i);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#manual_swap

warning: the loop variable `i` is only used to index `table`. Consider using `for item in table.iter().take(4)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:437:5
    |>
437 |>     for i in 0..4 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: this looks like you are swapping elements of `mval` manually, #[warn(manual_swap)] on by default
   --> src/huffman/mod.rs:448:7
    |>
448 |>       let t: u16 = mval[3];
    |>       ^
help: try
src/huffman/mod.rs:          mval.swap(3, 2);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#manual_swap

warning: the loop variable `i` is used to index `table`. Consider using `for (i, item) in table.iter().enumerate().take(7)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:452:5
    |>
452 |>     for i in 0..7 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them, #[warn(char_lit_as_u8)] on by default
   --> src/transform.rs:722:26
    |>
722 |>     if (fast!((p)[0]) >= 'a' as u8 && fast!((p)[0]) <= 'z' as u8) {
    |>                          ^^^^^^^^^
help: Consider using a byte literal instead:
b'a'
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8

warning: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them, #[warn(char_lit_as_u8)] on by default
   --> src/transform.rs:722:56
    |>
722 |>     if (fast!((p)[0]) >= 'a' as u8 && fast!((p)[0]) <= 'z' as u8) {
    |>                                                        ^^^^^^^^^
help: Consider using a byte literal instead:
b'z'
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/transform.rs:753:5
    |>
753 |>     let mut skip: i32;
    |>     ^
help: it is more idiomatic to write
src/transform.rs:        let  skip = if t < kOmitFirst1 { 0 } else { t as i32 - (kOmitFirst1 - 1) as i32 };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/transform.rs:763:12
    |>
763 |>     word = &fast!((word)[skip as usize;]);
    |>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:166:26
    |>
166 |> fn DecodeMetaBlockLength<'a,
    |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you have declared `#[inline(always)]` on `DecodeSymbol`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/decode.rs:301:1
    |>
301 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `ReadSymbol`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/decode.rs:319:1
    |>
319 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:321:71
    |>
321 |>   return DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br);
    |>                                                                       ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: The function/method "bit_reader::BrotliGetAvailableBits" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:330:63
    |>
330 |>   let mut available_bits = bit_reader::BrotliGetAvailableBits(&mut br);
    |>                                                               ^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:338:51
    |>
338 |>   let mut val = bit_reader::BrotliGetBitsUnmasked(&br) as u32;
    |>                                                   ^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:374:33
    |>
374 |>     *result = DecodeSymbol(val, &table, br);
    |>                                 ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:379:27
    |>
379 |>   return SafeDecodeSymbol(&table, br, result);
    |>                           ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/decode.rs:406:3
    |>
406 |>   let mut result = *value;
    |>   ^
help: it is more idiomatic to write
src/decode.rs:      let  result = if *bits > HUFFMAN_TABLE_BITS { ..; ext.value as u32 } else { ..; *value };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:438:29
    |>
438 |> fn ReadSimpleHuffmanSymbols<'a,
    |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this function has too many arguments (9/7), #[warn(too_many_arguments)] on by default
   --> src/decode.rs:489:1
    |>
489 |> fn ProcessSingleCodeLength(code_len: u32,
    |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: this function has too many arguments (12/7), #[warn(too_many_arguments)] on by default
   --> src/decode.rs:524:1
    |>
524 |> fn ProcessRepeatedCodeLength(code_len: u32,
    |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/decode.rs:537:3
    |>
537 |>   let mut new_len: u32 = 0;
    |>   ^
help: it is more idiomatic to write
src/decode.rs:      let  new_len = if (code_len == kCodeLengthRepeatCode) { *prev_code_len } else { 0 };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:581:26
    |>
581 |> fn ReadSymbolCodeLengths<'a,
    |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:649:30
    |>
649 |> fn SafeReadSymbolCodeLengths<'a,
    |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:718:30
    |>
718 |> fn ReadCodeLengthCodeLengths<'a,
    |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: manual implementation of an assign operation, #[warn(assign_op_pattern)] on by default
   --> src/decode.rs:757:7
    |>
757 |>       space = space - (32 >> v);
    |>       ^^^^^^^^^^^^^^^^^^^^^^^^^
help: replace it with
src/decode.rs:          space -= (32 >> v);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:786:20
    |>
786 |> fn ReadHuffmanCode<'a,
    |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:863:9
    |>
863 |>         match opt_table_size {
    |>         ^
help: try this
src/decode.rs:            if let Some(opt_table_size_ref) = opt_table_size { *opt_table_size_ref = table_size }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: The function/method "huffman::BrotliBuildCodeLengthsHuffmanTable" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:880:53
    |>
880 |>                                                     &mut s.code_length_code_lengths,
    |>                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: The function/method "huffman::BrotliBuildCodeLengthsHuffmanTable" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:881:53
    |>
881 |>                                                     &mut s.code_length_histo);
    |>                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: the variable `i` is used as a loop counter. Consider using `for (i, item) in fast_mut!((s.next_symbol)[0; max_code_length]).iter_mut().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
   --> src/decode.rs:888:9
    |>
888 |>         for next_symbol_mut in fast_mut!((s.next_symbol)[0; max_code_length]).iter_mut() {
    |>         ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:907:9
    |>
907 |>         match result {
    |>         ^
help: try this
src/decode.rs:            if let BrotliResult::NeedsMoreInput = result {
src/decode.rs:      result = SafeReadSymbolCodeLengths(alphabet_size, s, input)
src/decode.rs:    }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:927:9
    |>
927 |>         match opt_table_size {
    |>         ^
help: try this
src/decode.rs:            if let Some(opt_table_size_ref) = opt_table_size { *opt_table_size_ref = table_size }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:963:27
    |>
963 |>       if (!SafeReadSymbol(&table, &mut br, &mut index, input)) {
    |>                           ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: the variable `i` is used as a loop counter. Consider using `for (i, item) in fast_mut!((mtf)[0;(upper_bound as usize + 1usize)]).iter_mut().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
    --> src/decode.rs:1026:3
     |>
1026 |>   for item in fast_mut!((mtf)[0;(upper_bound as usize + 1usize)]).iter_mut() {
     |>   ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1055:27
     |>
1055 |> fn HuffmanTreeGroupDecode<'a,
     |>                           ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:1133:3
     |>
1133 |>   match result {
     |>   ^
help: try this
src/decode.rs:       if let BrotliResult::ResultSuccess = result {
src/decode.rs:       s.substate_tree_group = BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1159:26
     |>
1159 |> fn DecodeContextMapInner<'a,
     |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1240:9
     |>
1240 |>         let mut rleCodeGoto: bool = false;
     |>         ^
help: it is more idiomatic to write
src/decode.rs:             let  rleCodeGoto = if (code != 0xFFFF) { true } else { false };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1315:21
     |>
1315 |> fn DecodeContextMap<'a,
     |>                     ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1331:3
     |>
1331 |>   let mut context_map_arg: AllocU8::AllocatedMemory;
     |>   ^
help: it is more idiomatic to write
src/decode.rs:       let  context_map_arg = if is_dist_context_map { ..; mem::replace(&mut s.dist_context_map, AllocU8::AllocatedMemory::default()) } else { ..; mem::replace(&mut s.context_map, AllocU8::AllocatedMemory::default()) };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1461:37
     |>
1461 |> fn DecodeCommandBlockSwitchInternal<'a,
     |>                                     ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1477:29
     |>
1477 |> fn DecodeCommandBlockSwitch<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1486:33
     |>
1486 |> fn SafeDecodeCommandBlockSwitch<'a,
     |>                                 ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1498:38
     |>
1498 |> fn DecodeDistanceBlockSwitchInternal<'a,
     |>                                      ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1517:30
     |>
1517 |> fn DecodeDistanceBlockSwitch<'a,
     |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1527:34
     |>
1527 |> fn SafeDecodeDistanceBlockSwitch<'a,
     |>                                  ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1537:20
     |>
1537 |> fn WriteRingBuffer<'a,
     |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1547:3
     |>
1547 |>   let pos: usize;
     |>   ^
help: it is more idiomatic to write
src/decode.rs:       let pos = if s.pos > s.ringbuffer_size { s.ringbuffer_size as usize } else { s.pos as usize };
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1578:34
     |>
1578 |> fn CopyUncompressedBlockToOutput<'a,
     |>                                  ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1636:29
     |>
1636 |> fn BrotliAllocateRingBuffer<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:1653:5
     |>
1653 |>     if (next_block_header != -1) {
     |>     ^
help: try
src/decode.rs:         if ((next_block_header != -1)) && ((next_block_header & 3) == 3) {
src/decode.rs:       // ISLAST and ISEMPTY
src/decode.rs:       is_last = 1;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1695:25
     |>
1695 |> pub fn ReadContextModes<'a,
     |>                         ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1723:35
     |>
1723 |> pub fn TakeDistanceFromRingBuffer<'a,
     |>                                   ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1771:29
     |>
1771 |> pub fn ReadDistanceInternal<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: The function/method "bit_reader::BrotliBitReaderRestoreState" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
    --> src/decode.rs:1823:62
     |>
1823 |>           bit_reader::BrotliBitReaderRestoreState(&mut s.br, &mut memento);
     |>                                                              ^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1841:28
     |>
1841 |> pub fn ReadCommandInternal<'a,
     |>                            ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:1882:10
     |>
1882 |>   } else {
     |>          ^
help: try
src/decode.rs:       } else if (!SafeReadBits(&mut s.br,
src/decode.rs:                       v.insert_len_extra_bits as u32,
src/decode.rs:                       &mut insert_len_extra,
src/decode.rs:                       input)) ||
src/decode.rs:        (!SafeReadBits(&mut s.br,
src/decode.rs:                       v.copy_len_extra_bits as u32,
                   ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `memmove16`. This is usually a bad idea, #[warn(inline_always)] on by default
    --> src/decode.rs:1916:1
     |>
1916 |> #[inline(always)]
     |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: The function/method "clone_from_slice" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
    --> src/decode.rs:1941:80
     |>
1941 |>   fast_mut!((data)[off_dst as usize ; off_dst as usize + 16]).clone_from_slice(&mut local_array);
     |>                                                                                ^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: the function has a cyclomatic complexity of 46, #[warn(cyclomatic_complexity)] on by default
    --> src/decode.rs:1961:1
     |>
1961 |> fn ProcessCommandsInternal,
     |> ^
help: you could split it up into multiple smaller functions
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2104:22
     |>
2104 |>                 hc = &fast!((literal_hgroup)[i as usize]);
     |>                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2334:20
     |>
2334 |> fn ProcessCommands<'a,
     |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2344:24
     |>
2344 |> fn SafeProcessCommands<'a,
     |>                        ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2357:31
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |>                               ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: the function has a cyclomatic complexity of 55, #[warn(cyclomatic_complexity)] on by default
    --> src/decode.rs:2357:1
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |> ^
help: you could split it up into multiple smaller functions
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity

warning: this function has too many arguments (8/7), #[warn(too_many_arguments)] on by default
    --> src/decode.rs:2357:1
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: using `clone` on a `Copy` type, #[warn(clone_on_copy)] on by default
    --> src/decode.rs:2373:35
     |>
2373 |>   let mut saved_buffer: [u8; 8] = s.buffer.clone();
     |>                                   ^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:2532:11
     |>
2532 |>           if (s.is_metadata != 0 || s.is_uncompressed != 0) {
     |>           ^
help: try
src/decode.rs:               if ((s.is_metadata != 0 || s.is_uncompressed != 0)) && ((!bit_reader::BrotliJumpToByteBoundary(&mut s.br))) {
src/decode.rs:       result = BROTLI_FAILURE();
src/decode.rs:       break;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:2546:11
     |>
2546 |>           if (s.ringbuffer.slice().len() == 0) {
     |>           ^
help: try
src/decode.rs:               if (s.ringbuffer.slice().len() == 0) && ((!BrotliAllocateRingBuffer(&mut s, local_input))) {
src/decode.rs:       result = BROTLI_FAILURE();
src/decode.rs:       break;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:2586:11
     |>
2586 |>           match result {
     |>           ^
help: try this
src/decode.rs:               if let BrotliResult::ResultSuccess = result {
src/decode.rs:       s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: the variable `j` is used as a loop counter. Consider using `for (j, item) in fast_slice!((s.context_map)[0 ; bound]).iter().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
    --> src/decode.rs:2734:11
     |>
2734 |>           for context_map_item in fast_slice!((s.context_map)[0 ; bound]).iter() {
     |>           ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2794:33
     |>
2794 |>             s.context_lookup1 = &fast!((kContextLookup)[index1;]);
     |>                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2796:33
     |>
2796 |>             s.context_lookup2 = &fast!((kContextLookup)[index2;]);
     |>                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:2808:11
     |>
2808 |>           match result {
     |>           ^
help: try this
src/decode.rs:               if let BrotliResult::NeedsMoreInput = result { result = SafeProcessCommands(s, local_input) }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this function has too many arguments (8/7), #[warn(too_many_arguments)] on by default
   --> src/lib.rs:124:1
    |>
124 |> pub fn BrotliDecompressCustomIo ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: very complex type used. Consider factoring parts into `type` definitions, #[warn(type_complexity)] on by default
   --> src/lib.rs:266:34
    |>
266 |> pub struct Decompressor(DecompressorCustomAlloc                                  ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#type_complexity

warning: equality checks against false can be replaced by a negation, #[warn(bool_comparison)] on by default
   --> src/lib.rs:403:40
    |>
403 |>       while avail_out == buf.len() && (needs_input == false || self.input_eof == false) {
    |>                                        ^^^^^^^^^^^^^^^^^^^^
help: try simplifying it as shown:
src/lib.rs:          while avail_out == buf.len() && (!needs_input || self.input_eof == false) {
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison

warning: equality checks against false can be replaced by a negation, #[warn(bool_comparison)] on by default
   --> src/lib.rs:403:64
    |>
403 |>       while avail_out == buf.len() && (needs_input == false || self.input_eof == false) {
    |>                                                                ^^^^^^^^^^^^^^^^^^^^^^^
help: try simplifying it as shown:
src/lib.rs:          while avail_out == buf.len() && (needs_input == false || !self.input_eof) {
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/lib.rs:452:9
    |>
452 |>         match e.kind() {
    |>         ^
help: try this
src/lib.rs:            if let io::ErrorKind::Interrupted = e.kind() { continue }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/lib.rs:464:15
    |>
464 |>               match e.kind() {
    |>               ^
help: try this
src/lib.rs:                  if let io::ErrorKind::Interrupted = e.kind() { continue }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match
   Compiling brotli v1.0.6 (file:///Users/pascal/Projekte/tools/rust-brotli)
warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:45:5
   |>
45 |>     return BrotliBitReader {
   |>     ^
help: remove `return` as shown:
src/bit_reader/mod.rs:       BrotliBitReader {
src/bit_reader/mod.rs:         val_: 0,
src/bit_reader/mod.rs:         bit_pos_: 0,
src/bit_reader/mod.rs:         next_in: 0,
src/bit_reader/mod.rs:         avail_in: 0,
src/bit_reader/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:63:5
   |>
63 |>     return BrotliBitReaderState {
   |>     ^
help: remove `return` as shown:
src/bit_reader/mod.rs:       BrotliBitReaderState {
src/bit_reader/mod.rs:         val_: 0,
src/bit_reader/mod.rs:         bit_pos_: 0,
src/bit_reader/mod.rs:         next_in: 0,
src/bit_reader/mod.rs:         avail_in: 0,
src/bit_reader/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:74:3
   |>
74 |>   return BrotliBitReaderState {
   |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:     BrotliBitReaderState {
src/bit_reader/mod.rs:       val_: from.val_,
src/bit_reader/mod.rs:       bit_pos_: from.bit_pos_,
src/bit_reader/mod.rs:       next_in: from.next_in,
src/bit_reader/mod.rs:       avail_in: from.avail_in,
src/bit_reader/mod.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:90:3
   |>
90 |>   return ((::core::mem::size_of::() as u32) << 3) - br.bit_pos_;
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:     ((::core::mem::size_of::() as u32) << 3) - br.bit_pos_
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bit_reader/mod.rs:96:3
   |>
96 |>   return br.avail_in + (BrotliGetAvailableBits(br) >> 3);
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:     br.avail_in + (BrotliGetAvailableBits(br) >> 3)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:102:3
    |>
102 |>   return br.avail_in >= num;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      br.avail_in >= num
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:109:3
    |>
109 |>   return (fast!((input)[next_in]) as u16) | ((fast!((input)[next_in + 1]) as u16) << 8);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (fast!((input)[next_in]) as u16) | ((fast!((input)[next_in + 1]) as u16) << 8)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:118:3
    |>
118 |>   return (four_byte[0] as u32) | ((four_byte[1] as u32) << 8) | ((four_byte[2] as u32) << 16) |
    |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (four_byte[0] as u32) | ((four_byte[1] as u32) << 8) | ((four_byte[2] as u32) << 16) |
src/bit_reader/mod.rs:             ((four_byte[3] as u32) << 24)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:127:3
    |>
127 |>   return (eight_byte[0] as u64) | ((eight_byte[1] as u64) << 8) | ((eight_byte[2] as u64) << 16) |
    |>   ^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (eight_byte[0] as u64) | ((eight_byte[1] as u64) << 8) | ((eight_byte[2] as u64) << 16) |
src/bit_reader/mod.rs:             ((eight_byte[3] as u64) << 24) |
src/bit_reader/mod.rs:             ((eight_byte[4] as u64) << 32) | ((eight_byte[5] as u64) << 40) |
src/bit_reader/mod.rs:             ((eight_byte[6] as u64) << 48) | ((eight_byte[7] as u64) << 56)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:255:3
    |>
255 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:262:3
    |>
262 |>   return br.val_ >> br.bit_pos_;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      br.val_ >> br.bit_pos_
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:270:3
    |>
270 |>   return (BrotliGetBitsUnmasked(br) & (0xffffffffu32 as reg_t)) as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) & (0xffffffffu32 as reg_t)) as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:276:3
    |>
276 |>   return (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:283:3
    |>
283 |>   return (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      (BrotliGetBitsUnmasked(br) as u32) & BitMask(n_bits)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:299:3
    |>
299 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:341:5
    |>
341 |>     return val;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        val
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:349:5
    |>
349 |>     return low_val | (high_val << 16);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        low_val | (high_val << 16)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:361:5
    |>
361 |>     return val;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        val
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:369:5
    |>
369 |>     return low_val | (high_val << 16);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:        low_val | (high_val << 16)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:386:3
    |>
386 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:397:3
    |>
397 |>   return pad_bits == 0;
    |>   ^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      pad_bits == 0
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:414:3
    |>
414 |>   return -1;
    |>   ^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      -1
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bit_reader/mod.rs:459:3
    |>
459 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/bit_reader/mod.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:34:5
   |>
34 |>     return self.value == other.value && self.bits == other.bits;
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:       self.value == other.value && self.bits == other.bits
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:40:5
   |>
40 |>     return HuffmanCode {
   |>     ^
help: remove `return` as shown:
src/huffman/mod.rs:       HuffmanCode {
src/huffman/mod.rs:         value: 0,
src/huffman/mod.rs:         bits: 0,
src/huffman/mod.rs:       }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:79:9
   |>
79 |>         return fast_mut!((self.codes.slice_mut())[start;]);
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:           &mut $slice[$start..]
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/huffman/mod.rs:84:9
   |>
84 |>         return & fast_slice!((self.codes)[start;]);
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:           & fast_slice!((self.codes)[start;])
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:107:7
    |>
107 |>       return ret;
    |>       ^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:          ret
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:114:9
    |>
114 |>         return HuffmanTreeGroup:: {
    |>         ^
help: remove `return` as shown:
src/huffman/mod.rs:            HuffmanTreeGroup:: {
src/huffman/mod.rs:                htrees : AllocU32::AllocatedMemory::default(),
src/huffman/mod.rs:                codes : AllocHC::AllocatedMemory::default(),
src/huffman/mod.rs:                alphabet_size : 0,
src/huffman/mod.rs:                num_htrees : 0,
src/huffman/mod.rs:            }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:153:3
    |>
153 |>   return fast!((kReverseBits)[num as usize]) as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      fast!((kReverseBits)[num as usize]) as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:185:3
    |>
185 |>   return len - root_bits;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      len - root_bits
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:378:3
    |>
378 |>   return total_size as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      total_size as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/huffman/mod.rs:472:3
    |>
472 |>   return goal_size;
    |>   ^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/huffman/mod.rs:      goal_size
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:336:9
    |>
336 |>         return retval;
    |>         ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:            retval
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:400:17
    |>
400 |>                 return BrotliGetAvailableBits(&self.br) == 0,
    |>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                    BrotliGetAvailableBits(&self.br) == 0,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:401:18
    |>
401 |>             _ => return false,
    |>                  ^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                _ => false,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:407:54
    |>
407 |>             BrotliRunningState::BROTLI_STATE_DONE => return true,
    |>                                                      ^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                BrotliRunningState::BROTLI_STATE_DONE => true,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/state.rs:408:18
    |>
408 |>             _ => return false,
    |>                  ^^^^^^^^^^^^
help: remove `return` as shown:
src/state.rs:                _ => false,
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/transform.rs:734:3
    |>
734 |>   return 3;
    |>   ^^^^^^^^^
help: remove `return` as shown:
src/transform.rs:      3
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/transform.rs:794:5
    |>
794 |>     return idx;
    |>     ^^^^^^^^^^^
help: remove `return` as shown:
src/transform.rs:        idx
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/decode.rs:74:3
   |>
74 |>   return BrotliResult::ResultFailure;
   |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:     BrotliResult::ResultFailure
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:110:3
    |>
110 |>   return 17;
    |>   ^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      17
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:314:3
    |>
314 |>   return table_element.value as u32;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      table_element.value as u32
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:321:3
    |>
321 |>   return DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:364:3
    |>
364 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:379:3
    |>
379 |>   return SafeDecodeSymbol(&table, br, result);
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      SafeDecodeSymbol(&table, br, result)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:421:3
    |>
421 |>   return result;
    |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:430:3
    |>
430 |>   return result;
    |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:479:3
    |>
479 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:646:3
    |>
646 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:713:3
    |>
713 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:770:3
    |>
770 |>   return BrotliResult::ResultSuccess;
    |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:947:3
    |>
947 |>   return fast_ref!((prefix::kBlockLengthPrefixCode)[code as usize]).offset as u32 +
    |>   ^
help: remove `return` as shown:
src/decode.rs:      fast_ref!((prefix::kBlockLengthPrefixCode)[code as usize]).offset as u32 +
src/decode.rs:             bit_reader::BrotliReadBits(br, nbits, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:966:7
    |>
966 |>       return (true, index);
    |>       ^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:          (true, index)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:968:10
    |>
968 |>     _ => return (true, block_length_index),
    |>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:        _ => (true, block_length_index),
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/decode.rs:992:3
    |>
992 |>   return true;
    |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:      true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1139:3
     |>
1139 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1354:3
     |>
1354 |>   return retval;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       retval
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1410:3
     |>
1410 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1439:3
     |>
1439 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1473:3
     |>
1473 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1493:3
     |>
1493 |>   return DecodeCommandBlockSwitchInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       DecodeCommandBlockSwitchInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1513:3
     |>
1513 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1534:3
     |>
1534 |>   return DecodeDistanceBlockSwitchInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       DecodeDistanceBlockSwitchInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1575:3
     |>
1575 |>   return BrotliResult::ResultSuccess;
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1691:3
     |>
1691 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1720:3
     |>
1720 |>   return BrotliResult::ResultSuccess;
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       BrotliResult::ResultSuccess
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1763:5
     |>
1763 |>     return bit_reader::BrotliSafeReadBits(br, n_bits, val, input);
     |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:         bit_reader::BrotliSafeReadBits(br, n_bits, val, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1766:5
     |>
1766 |>     return true;
     |>     ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:         true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1837:3
     |>
1837 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1898:3
     |>
1898 |>   return true;
     |>   ^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       true
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1906:3
     |>
1906 |>   return bit_reader::BrotliWarmupBitReader(br, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       bit_reader::BrotliWarmupBitReader(br, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:1913:3
     |>
1913 |>   return bit_reader::BrotliCheckInputAmount(br, num);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       bit_reader::BrotliCheckInputAmount(br, num)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2331:3
     |>
2331 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2341:3
     |>
2341 |>   return ProcessCommandsInternal(false, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       ProcessCommandsInternal(false, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2351:3
     |>
2351 |>   return ProcessCommandsInternal(true, s, input);
     |>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       ProcessCommandsInternal(true, s, input)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
    --> src/decode.rs:2908:3
     |>
2908 |>   return result;
     |>   ^^^^^^^^^^^^^^
help: remove `return` as shown:
src/decode.rs:       result
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/lib.rs:67:3
   |>
67 |>   return BrotliDecompressCustomAlloc(r,
   |>   ^
help: remove `return` as shown:
src/lib.rs:     BrotliDecompressCustomAlloc(r,
src/lib.rs:                                        w,
src/lib.rs:                                        &mut input_buffer[..],
src/lib.rs:                                        &mut output_buffer[..],
src/lib.rs:                                        HeapAlloc:: { default_value: 0 },
src/lib.rs:                                        HeapAlloc:: { default_value: 0 },
              ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:114:3
    |>
114 |>   return BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
    |>   ^
help: remove `return` as shown:
src/lib.rs:      BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
src/lib.rs:                                      &mut IoWriterWrapper::(w),
src/lib.rs:                                      input_buffer,
src/lib.rs:                                      output_buffer,
src/lib.rs:                                      alloc_u8,
src/lib.rs:                                      alloc_u32,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:238:9
    |>
238 |>         return DecompressorCustomAlloc::(
    |>         ^
help: remove `return` as shown:
src/lib.rs:            DecompressorCustomAlloc::(
src/lib.rs:              DecompressorCustomIo::,
src/lib.rs:                                     BufferType,
src/lib.rs:                                     AllocU8, AllocU32, AllocHC>::new(IntoIoReader::(r),
src/lib.rs:                                                                      buffer,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:260:8
    |>
260 |>        return self.0.read(buf);
    |>        ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:           self.0.read(buf)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:281:5
    |>
281 |>     return Decompressor::(DecompressorCustomAlloc::     ^
help: remove `return` as shown:
src/lib.rs:        Decompressor::(DecompressorCustomAlloc::
src/lib.rs:                                                            as Allocator>::AllocatedMemory,
src/lib.rs:                                                           HeapAlloc,
src/lib.rs:                                                           HeapAlloc,
src/lib.rs:                                                           HeapAlloc >::new(r,
               ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:325:5
    |>
325 |>     return self.0.read(buf);
    |>     ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:        self.0.read(buf)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:372:9
    |>
372 |>         return ret;
    |>         ^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:            ret
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:441:7
    |>
441 |>       return Ok(output_offset);
    |>       ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:          Ok(output_offset)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/lib.rs:476:3
    |>
476 |>   return Ok(out_size);
    |>   ^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/lib.rs:      Ok(out_size)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: you have declared `#[inline(always)]` on `BrotliLoad16LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:106:1
    |>
106 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliLoad32LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:113:1
    |>
113 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliLoad64LE`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:122:1
    |>
122 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliFillBitWindow`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:134:1
    |>
134 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:160:10
    |>
160 |>   } else {
    |>          ^
help: try
src/bit_reader/mod.rs:      } else if (BROTLI_ALIGNED_READ == 0 && (n_bits <= 8)) {
src/bit_reader/mod.rs:      if (br.bit_pos_ >= 24) {
src/bit_reader/mod.rs:        br.val_ >>= 24;
src/bit_reader/mod.rs:        br.bit_pos_ ^= 24;  // here same as -= 24 because of the if condition
src/bit_reader/mod.rs:        br.val_ |= (BrotliLoad32LE(input, br.next_in) << 8) as u64;
src/bit_reader/mod.rs:        br.avail_in -= 3;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:169:12
    |>
169 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 16 {
src/bit_reader/mod.rs:      br.val_ >>= 16;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 16;  /* here same as -= 16 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad16LE(input, br.next_in) as reg_t) << 16;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `BrotliFillBitWindowCompileTimeNbits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:181:1
    |>
181 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:211:10
    |>
211 |>   } else {
    |>          ^
help: try
src/bit_reader/mod.rs:      } else if
src/bit_reader/mod.rs:    // BROTLI_ALIGNED_READ == false &&
src/bit_reader/mod.rs:    n_bits <= 8 {
src/bit_reader/mod.rs:      // !BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {
src/bit_reader/mod.rs:      if br.bit_pos_ >= 24 {
src/bit_reader/mod.rs:        br.val_ >>= 24;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:202:12
    |>
202 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 32 {
src/bit_reader/mod.rs:      br.val_ >>= 32;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 32;  /* here same as -= 32 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad32LE(input, br.next_in) as reg_t) << 32;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:223:12
    |>
223 |>     } else {
    |>            ^
help: try
src/bit_reader/mod.rs:        } else if br.bit_pos_ >= 16 {
src/bit_reader/mod.rs:      br.val_ >>= 16;
src/bit_reader/mod.rs:      br.bit_pos_ ^= 16;  /* here same as -= 16 because of the if condition */
src/bit_reader/mod.rs:      br.val_ |= (BrotliLoad16LE(input, br.next_in) as reg_t) << 16;
src/bit_reader/mod.rs:      br.avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
src/bit_reader/mod.rs:      br.next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
                          ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `BrotliGetBitsUnmasked`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:260:1
    |>
260 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliGet16BitsUnmasked`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:267:1
    |>
267 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliDropBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:303:1
    |>
303 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliTakeBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:323:1
    |>
323 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `BrotliReadBits`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/bit_reader/mod.rs:335:1
    |>
335 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
   --> src/bit_reader/mod.rs:446:3
    |>
446 |>   if BrotliGetAvailableBits(br) == 0 {
    |>   ^
help: try
src/bit_reader/mod.rs:      if BrotliGetAvailableBits(br) == 0 && (!BrotliPullByte(br, input)) {
src/bit_reader/mod.rs:      return false;
src/bit_reader/mod.rs:    }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: defining a method called `eq` on this type; consider implementing the `std::cmp::PartialEq` trait or choosing a less ambiguous name, #[warn(should_implement_trait)] on by default
  --> src/huffman/mod.rs:33:3
   |>
33 |>   pub fn eq(&self, other: &Self) -> bool {
   |>   ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
  --> src/huffman/mod.rs:77:5
   |>
77 |>     pub fn get_tree_mut<'a>(self :&'a mut Self, index : u32) -> &'a mut [HuffmanCode] {
   |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
  --> src/huffman/mod.rs:82:5
   |>
82 |>     pub fn get_tree<'a>(self :&'a Self, index : u32) -> &'a [HuffmanCode] {
   |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
  --> src/huffman/mod.rs:84:16
   |>
84 |>         return & fast_slice!((self.codes)[start;]);
   |>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: explicit lifetimes given in parameter types where they could be elided, #[warn(needless_lifetimes)] on by default
   --> src/huffman/mod.rs:100:5
    |>
100 |>     pub fn build_hgroup_cache<'a>(self : &'a Self) -> [&'a [HuffmanCode]; 256] {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: the variable `index` is used as a loop counter. Consider using `for (index, item) in self.htrees.slice().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
   --> src/huffman/mod.rs:103:7
    |>
103 |>       for htree in self.htrees.slice() {
    |>       ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/huffman/mod.rs:421:5
    |>
421 |>     let last: u16;
    |>     ^
help: it is more idiomatic to write
src/huffman/mod.rs:        let last = if val.len() > 3 { ($slice)[$index] } else { 65535 };
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: the loop variable `i` is used to index `mval`. Consider using `for (i, item) in mval.iter().enumerate().take(3)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:428:5
    |>
428 |>     for i in 0..3 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: the loop variable `k` is only used to index `mval`. Consider using `for item in mval.iter().take(4).skip(i + 1)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:429:7
    |>
429 |>       for k in i + 1..4 {
    |>       ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: this looks like you are swapping elements of `mval` manually, #[warn(manual_swap)] on by default
   --> src/huffman/mod.rs:431:11
    |>
431 |>           let t: u16 = mval[k];
    |>           ^
help: try
src/huffman/mod.rs:              mval.swap(k, i);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#manual_swap

warning: the loop variable `i` is only used to index `table`. Consider using `for item in table.iter().take(4)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:437:5
    |>
437 |>     for i in 0..4 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: this looks like you are swapping elements of `mval` manually, #[warn(manual_swap)] on by default
   --> src/huffman/mod.rs:448:7
    |>
448 |>       let t: u16 = mval[3];
    |>       ^
help: try
src/huffman/mod.rs:          mval.swap(3, 2);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#manual_swap

warning: the loop variable `i` is used to index `table`. Consider using `for (i, item) in table.iter().enumerate().take(7)` or similar iterators, #[warn(needless_range_loop)] on by default
   --> src/huffman/mod.rs:452:5
    |>
452 |>     for i in 0..7 {
    |>     ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_range_loop

warning: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them, #[warn(char_lit_as_u8)] on by default
   --> src/transform.rs:722:26
    |>
722 |>     if (fast!((p)[0]) >= 'a' as u8 && fast!((p)[0]) <= 'z' as u8) {
    |>                          ^^^^^^^^^
help: Consider using a byte literal instead:
b'a'
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8

warning: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them, #[warn(char_lit_as_u8)] on by default
   --> src/transform.rs:722:56
    |>
722 |>     if (fast!((p)[0]) >= 'a' as u8 && fast!((p)[0]) <= 'z' as u8) {
    |>                                                        ^^^^^^^^^
help: Consider using a byte literal instead:
b'z'
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/transform.rs:753:5
    |>
753 |>     let mut skip: i32;
    |>     ^
help: it is more idiomatic to write
src/transform.rs:        let  skip = if t < kOmitFirst1 { 0 } else { t as i32 - (kOmitFirst1 - 1) as i32 };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/transform.rs:763:12
    |>
763 |>     word = &fast!((word)[skip as usize;]);
    |>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:166:26
    |>
166 |> fn DecodeMetaBlockLength<'a,
    |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you have declared `#[inline(always)]` on `DecodeSymbol`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/decode.rs:301:1
    |>
301 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: you have declared `#[inline(always)]` on `ReadSymbol`. This is usually a bad idea, #[warn(inline_always)] on by default
   --> src/decode.rs:319:1
    |>
319 |> #[inline(always)]
    |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:321:71
    |>
321 |>   return DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br);
    |>                                                                       ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: The function/method "bit_reader::BrotliGetAvailableBits" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:330:63
    |>
330 |>   let mut available_bits = bit_reader::BrotliGetAvailableBits(&mut br);
    |>                                                               ^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:338:51
    |>
338 |>   let mut val = bit_reader::BrotliGetBitsUnmasked(&br) as u32;
    |>                                                   ^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:374:33
    |>
374 |>     *result = DecodeSymbol(val, &table, br);
    |>                                 ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:379:27
    |>
379 |>   return SafeDecodeSymbol(&table, br, result);
    |>                           ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/decode.rs:406:3
    |>
406 |>   let mut result = *value;
    |>   ^
help: it is more idiomatic to write
src/decode.rs:      let  result = if *bits > HUFFMAN_TABLE_BITS { ..; ext.value as u32 } else { ..; *value };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:438:29
    |>
438 |> fn ReadSimpleHuffmanSymbols<'a,
    |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this function has too many arguments (9/7), #[warn(too_many_arguments)] on by default
   --> src/decode.rs:489:1
    |>
489 |> fn ProcessSingleCodeLength(code_len: u32,
    |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: this function has too many arguments (12/7), #[warn(too_many_arguments)] on by default
   --> src/decode.rs:524:1
    |>
524 |> fn ProcessRepeatedCodeLength(code_len: u32,
    |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
   --> src/decode.rs:537:3
    |>
537 |>   let mut new_len: u32 = 0;
    |>   ^
help: it is more idiomatic to write
src/decode.rs:      let  new_len = if (code_len == kCodeLengthRepeatCode) { *prev_code_len } else { 0 };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:581:26
    |>
581 |> fn ReadSymbolCodeLengths<'a,
    |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:649:30
    |>
649 |> fn SafeReadSymbolCodeLengths<'a,
    |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:718:30
    |>
718 |> fn ReadCodeLengthCodeLengths<'a,
    |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: manual implementation of an assign operation, #[warn(assign_op_pattern)] on by default
   --> src/decode.rs:757:7
    |>
757 |>       space = space - (32 >> v);
    |>       ^^^^^^^^^^^^^^^^^^^^^^^^^
help: replace it with
src/decode.rs:          space -= (32 >> v);
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
   --> src/decode.rs:786:20
    |>
786 |> fn ReadHuffmanCode<'a,
    |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:863:9
    |>
863 |>         match opt_table_size {
    |>         ^
help: try this
src/decode.rs:            if let Some(opt_table_size_ref) = opt_table_size { *opt_table_size_ref = table_size }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: The function/method "huffman::BrotliBuildCodeLengthsHuffmanTable" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:880:53
    |>
880 |>                                                     &mut s.code_length_code_lengths,
    |>                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: The function/method "huffman::BrotliBuildCodeLengthsHuffmanTable" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
   --> src/decode.rs:881:53
    |>
881 |>                                                     &mut s.code_length_histo);
    |>                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: the variable `i` is used as a loop counter. Consider using `for (i, item) in fast_mut!((s.next_symbol)[0; max_code_length]).iter_mut().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
   --> src/decode.rs:888:9
    |>
888 |>         for next_symbol_mut in fast_mut!((s.next_symbol)[0; max_code_length]).iter_mut() {
    |>         ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:907:9
    |>
907 |>         match result {
    |>         ^
help: try this
src/decode.rs:            if let BrotliResult::NeedsMoreInput = result {
src/decode.rs:      result = SafeReadSymbolCodeLengths(alphabet_size, s, input)
src/decode.rs:    }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/decode.rs:927:9
    |>
927 |>         match opt_table_size {
    |>         ^
help: try this
src/decode.rs:            if let Some(opt_table_size_ref) = opt_table_size { *opt_table_size_ref = table_size }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
   --> src/decode.rs:963:27
    |>
963 |>       if (!SafeReadSymbol(&table, &mut br, &mut index, input)) {
    |>                           ^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: the variable `i` is used as a loop counter. Consider using `for (i, item) in fast_mut!((mtf)[0;(upper_bound as usize + 1usize)]).iter_mut().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
    --> src/decode.rs:1026:3
     |>
1026 |>   for item in fast_mut!((mtf)[0;(upper_bound as usize + 1usize)]).iter_mut() {
     |>   ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1055:27
     |>
1055 |> fn HuffmanTreeGroupDecode<'a,
     |>                           ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:1133:3
     |>
1133 |>   match result {
     |>   ^
help: try this
src/decode.rs:       if let BrotliResult::ResultSuccess = result {
src/decode.rs:       s.substate_tree_group = BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1159:26
     |>
1159 |> fn DecodeContextMapInner<'a,
     |>                          ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1240:9
     |>
1240 |>         let mut rleCodeGoto: bool = false;
     |>         ^
help: it is more idiomatic to write
src/decode.rs:             let  rleCodeGoto = if (code != 0xFFFF) { true } else { false };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1315:21
     |>
1315 |> fn DecodeContextMap<'a,
     |>                     ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1331:3
     |>
1331 |>   let mut context_map_arg: AllocU8::AllocatedMemory;
     |>   ^
help: it is more idiomatic to write
src/decode.rs:       let  context_map_arg = if is_dist_context_map { ..; mem::replace(&mut s.dist_context_map, AllocU8::AllocatedMemory::default()) } else { ..; mem::replace(&mut s.context_map, AllocU8::AllocatedMemory::default()) };
note: you might not need `mut` at all
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1461:37
     |>
1461 |> fn DecodeCommandBlockSwitchInternal<'a,
     |>                                     ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1477:29
     |>
1477 |> fn DecodeCommandBlockSwitch<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1486:33
     |>
1486 |> fn SafeDecodeCommandBlockSwitch<'a,
     |>                                 ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1498:38
     |>
1498 |> fn DecodeDistanceBlockSwitchInternal<'a,
     |>                                      ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1517:30
     |>
1517 |> fn DecodeDistanceBlockSwitch<'a,
     |>                              ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1527:34
     |>
1527 |> fn SafeDecodeDistanceBlockSwitch<'a,
     |>                                  ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1537:20
     |>
1537 |> fn WriteRingBuffer<'a,
     |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: `if _ { .. } else { .. }` is an expression, #[warn(useless_let_if_seq)] on by default
    --> src/decode.rs:1547:3
     |>
1547 |>   let pos: usize;
     |>   ^
help: it is more idiomatic to write
src/decode.rs:       let pos = if s.pos > s.ringbuffer_size { s.ringbuffer_size as usize } else { s.pos as usize };
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1578:34
     |>
1578 |> fn CopyUncompressedBlockToOutput<'a,
     |>                                  ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1636:29
     |>
1636 |> fn BrotliAllocateRingBuffer<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:1653:5
     |>
1653 |>     if (next_block_header != -1) {
     |>     ^
help: try
src/decode.rs:         if ((next_block_header != -1)) && ((next_block_header & 3) == 3) {
src/decode.rs:       // ISLAST and ISEMPTY
src/decode.rs:       is_last = 1;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1695:25
     |>
1695 |> pub fn ReadContextModes<'a,
     |>                         ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1723:35
     |>
1723 |> pub fn TakeDistanceFromRingBuffer<'a,
     |>                                   ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1771:29
     |>
1771 |> pub fn ReadDistanceInternal<'a,
     |>                             ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: The function/method "bit_reader::BrotliBitReaderRestoreState" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
    --> src/decode.rs:1823:62
     |>
1823 |>           bit_reader::BrotliBitReaderRestoreState(&mut s.br, &mut memento);
     |>                                                              ^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:1841:28
     |>
1841 |> pub fn ReadCommandInternal<'a,
     |>                            ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this `else { if .. }` block can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:1882:10
     |>
1882 |>   } else {
     |>          ^
help: try
src/decode.rs:       } else if (!SafeReadBits(&mut s.br,
src/decode.rs:                       v.insert_len_extra_bits as u32,
src/decode.rs:                       &mut insert_len_extra,
src/decode.rs:                       input)) ||
src/decode.rs:        (!SafeReadBits(&mut s.br,
src/decode.rs:                       v.copy_len_extra_bits as u32,
                   ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you have declared `#[inline(always)]` on `memmove16`. This is usually a bad idea, #[warn(inline_always)] on by default
    --> src/decode.rs:1916:1
     |>
1916 |> #[inline(always)]
     |> ^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#inline_always

warning: The function/method "clone_from_slice" doesn't need a mutable reference, #[warn(unnecessary_mut_passed)] on by default
    --> src/decode.rs:1941:80
     |>
1941 |>   fast_mut!((data)[off_dst as usize ; off_dst as usize + 16]).clone_from_slice(&mut local_array);
     |>                                                                                ^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unnecessary_mut_passed

warning: the function has a cyclomatic complexity of 46, #[warn(cyclomatic_complexity)] on by default
    --> src/decode.rs:1961:1
     |>
1961 |> fn ProcessCommandsInternal,
     |> ^
help: you could split it up into multiple smaller functions
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2104:22
     |>
2104 |>                 hc = &fast!((literal_hgroup)[i as usize]);
     |>                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2334:20
     |>
2334 |> fn ProcessCommands<'a,
     |>                    ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2344:24
     |>
2344 |> fn SafeProcessCommands<'a,
     |>                        ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: this lifetime isn't used in the function definition, #[warn(unused_lifetimes)] on by default
    --> src/decode.rs:2357:31
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |>                               ^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes

warning: the function has a cyclomatic complexity of 55, #[warn(cyclomatic_complexity)] on by default
    --> src/decode.rs:2357:1
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |> ^
help: you could split it up into multiple smaller functions
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity

warning: this function has too many arguments (8/7), #[warn(too_many_arguments)] on by default
    --> src/decode.rs:2357:1
     |>
2357 |> pub fn BrotliDecompressStream<'a,
     |> ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: using `clone` on a `Copy` type, #[warn(clone_on_copy)] on by default
    --> src/decode.rs:2373:35
     |>
2373 |>   let mut saved_buffer: [u8; 8] = s.buffer.clone();
     |>                                   ^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#clone_on_copy

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:2532:11
     |>
2532 |>           if (s.is_metadata != 0 || s.is_uncompressed != 0) {
     |>           ^
help: try
src/decode.rs:               if ((s.is_metadata != 0 || s.is_uncompressed != 0)) && ((!bit_reader::BrotliJumpToByteBoundary(&mut s.br))) {
src/decode.rs:       result = BROTLI_FAILURE();
src/decode.rs:       break;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: this if statement can be collapsed, #[warn(collapsible_if)] on by default
    --> src/decode.rs:2546:11
     |>
2546 |>           if (s.ringbuffer.slice().len() == 0) {
     |>           ^
help: try
src/decode.rs:               if (s.ringbuffer.slice().len() == 0) && ((!BrotliAllocateRingBuffer(&mut s, local_input))) {
src/decode.rs:       result = BROTLI_FAILURE();
src/decode.rs:       break;
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#collapsible_if

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:2586:11
     |>
2586 |>           match result {
     |>           ^
help: try this
src/decode.rs:               if let BrotliResult::ResultSuccess = result {
src/decode.rs:       s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE
src/decode.rs:     }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: the variable `j` is used as a loop counter. Consider using `for (j, item) in fast_slice!((s.context_map)[0 ; bound]).iter().enumerate()` or similar iterators, #[warn(explicit_counter_loop)] on by default
    --> src/decode.rs:2734:11
     |>
2734 |>           for context_map_item in fast_slice!((s.context_map)[0 ; bound]).iter() {
     |>           ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2794:33
     |>
2794 |>             s.context_lookup1 = &fast!((kContextLookup)[index1;]);
     |>                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: this expression borrows a reference that is immediately dereferenced by the compiler, #[warn(needless_borrow)] on by default
    --> src/decode.rs:2796:33
     |>
2796 |>             s.context_lookup2 = &fast!((kContextLookup)[index2;]);
     |>                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrow

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
    --> src/decode.rs:2808:11
     |>
2808 |>           match result {
     |>           ^
help: try this
src/decode.rs:               if let BrotliResult::NeedsMoreInput = result { result = SafeProcessCommands(s, local_input) }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: this function has too many arguments (8/7), #[warn(too_many_arguments)] on by default
   --> src/lib.rs:124:1
    |>
124 |> pub fn BrotliDecompressCustomIo ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#too_many_arguments

warning: very complex type used. Consider factoring parts into `type` definitions, #[warn(type_complexity)] on by default
   --> src/lib.rs:266:34
    |>
266 |> pub struct Decompressor(DecompressorCustomAlloc                                  ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#type_complexity

warning: equality checks against false can be replaced by a negation, #[warn(bool_comparison)] on by default
   --> src/lib.rs:403:40
    |>
403 |>       while avail_out == buf.len() && (needs_input == false || self.input_eof == false) {
    |>                                        ^^^^^^^^^^^^^^^^^^^^
help: try simplifying it as shown:
src/lib.rs:          while avail_out == buf.len() && (!needs_input || self.input_eof == false) {
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison

warning: equality checks against false can be replaced by a negation, #[warn(bool_comparison)] on by default
   --> src/lib.rs:403:64
    |>
403 |>       while avail_out == buf.len() && (needs_input == false || self.input_eof == false) {
    |>                                                                ^^^^^^^^^^^^^^^^^^^^^^^
help: try simplifying it as shown:
src/lib.rs:          while avail_out == buf.len() && (needs_input == false || !self.input_eof) {
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/lib.rs:452:9
    |>
452 |>         match e.kind() {
    |>         ^
help: try this
src/lib.rs:            if let io::ErrorKind::Interrupted = e.kind() { continue }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match

warning: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`, #[warn(single_match)] on by default
   --> src/lib.rs:464:15
    |>
464 |>               match e.kind() {
    |>               ^
help: try this
src/lib.rs:                  if let io::ErrorKind::Interrupted = e.kind() { continue }
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#single_match
warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:17:8
   |>
17 |>        return Rebox::{b : b};
   |>        ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:          Rebox::{b : b}
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:24:9
   |>
24 |>         return &(*self.b)[index]
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:           &(*self.b)[index]
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:30:9
   |>
30 |>         return &mut (*self.b)[index]
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:           &mut (*self.b)[index]
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:36:8
   |>
36 |>        return &*self.b
   |>        ^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:          &*self.b
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:42:8
   |>
42 |>        return &mut*self.b
   |>        ^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:          &mut*self.b
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
  --> src/bin/brotli.rs:56:8
   |>
56 |>        return Rebox::{b : b};
   |>        ^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:          Rebox::{b : b}
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bin/brotli.rs:158:5
    |>
158 |>     return brotli::BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
    |>     ^
help: remove `return` as shown:
src/bin/brotli.rs:        brotli::BrotliDecompressCustomIo(&mut IoReaderWrapper::(r),
src/bin/brotli.rs:                                        &mut IoWriterWrapper::(w),
src/bin/brotli.rs:                                        input_buffer.slice_mut(), output_buffer.slice_mut(),
src/bin/brotli.rs:                                        alloc_u8,
src/bin/brotli.rs:                                        HeapAllocator::{default_value:0},
src/bin/brotli.rs:                                        HeapAllocator::{default_value:HuffmanCode::default()},
                      ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bin/brotli.rs:189:9
    |>
189 |>         return BrotliDecompressor::(
    |>         ^
help: remove `return` as shown:
src/bin/brotli.rs:            BrotliDecompressor::(
src/bin/brotli.rs:              brotli::DecompressorCustomIo::,
src/bin/brotli.rs:                                     Rebox,
src/bin/brotli.rs:                                     HeapAllocator, HeapAllocator, HeapAllocator >
src/bin/brotli.rs:                                     ::new(IntoIoReader::(r),
                      ...
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: unneeded return statement, #[warn(needless_return)] on by default
   --> src/bin/brotli.rs:204:8
    |>
204 |>        return self.0.read(buf);
    |>        ^^^^^^^^^^^^^^^^^^^^^^^^
help: remove `return` as shown:
src/bin/brotli.rs:           self.0.read(buf)
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_return

warning: very complex type used. Consider factoring parts into `type` definitions, #[warn(type_complexity)] on by default
   --> src/bin/brotli.rs:174:40
    |>
174 |> pub struct BrotliDecompressor(brotli::DecompressorCustomIo                                        ^
help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#type_complexity

BrotliEncode stalls forever

The following stalls forever with brotli = { version = "3.3" , features = ["std"] }

let mut src = vec![27; 10<<10];
let mut src = Cursor::new(src);

let mut dest = Vec::with_capacity(10<<9);
let mut dest = Cursor::new(&mut dest);
BrotliEncode(&mut src, &mut dest, &Default::default()).unwrap()

Few tests fail with OOM on 32bit

failures:
---- enc::test::test_roundtrip_compressed_repeated stdout ----
thread 'enc::test::test_roundtrip_compressed_repeated' panicked at 'OOM', /usr/share/cargo/registry/alloc-no-stdlib-2.0.1/src/stack_allocator.rs:52:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
---- enc::test::test_roundtrip_ukkonooa stdout ----
thread 'enc::test::test_roundtrip_ukkonooa' panicked at 'OOM', /usr/share/cargo/registry/alloc-no-stdlib-2.0.1/src/stack_allocator.rs:52:13
failures:
    enc::test::test_roundtrip_compressed_repeated
    enc::test::test_roundtrip_ukkonooa

Overflow on 32bit target

I've been working on some WebAssembly projects using the wasm32-unknown-unknown target and I sometimes get a panic / abort.

To reproduce this issue, I made a small crate which one can use with cargo run and a target of i686-unknown-linux-gnu (this may fail to build on 64bit machines; I had to use a 32bit Ubuntu VM). Running that gives this error:

thread 'main' panicked at 'attempt to shift right with overflow', /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1131:34

Cargo.toml

[package]
name = "test-brotli-32bit-target"
version = "0.0.0"

[dependencies]
brotli = "1.1.0"

main.rs

extern crate brotli;

use brotli::{BrotliCompress, BrotliDecompress};
use brotli::enc::{BrotliEncoderInitParams};

fn main() {
    let mut input: &[u8] = b"
      <!doctype html>
      <html>
        <head>
          <title>Testing!</title>
        </head>
        <body>
          <h1>Hello, world!</h1>
        </body>
      </html>
    ";

    let mut compressed_input = vec![];
    let params = BrotliEncoderInitParams();
    BrotliCompress(&mut input, &mut compressed_input, &params).unwrap();

    let mut result = vec![];
    match BrotliDecompress(&mut compressed_input.as_slice(), &mut result) {
        Ok(_) => println!("Success! {:?}", result),
        Err(e) => println!("Error! {:?}", e),
    }
}
Here's the full Rust backtrace
    
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/test-brotli-32bit-target`
thread 'main' panicked at 'attempt to shift right with overflow', /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1131:34
stack backtrace:
   0: 0x8012d18d - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::h56cb4e8fab26ca56
                       at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: 0x8012f603 - std::sys_common::backtrace::print::hdde3d983397ec5dc
                       at /checkout/src/libstd/sys_common/backtrace.rs:68
                       at /checkout/src/libstd/sys_common/backtrace.rs:57
   2: 0x80129e96 - std::panicking::default_hook::{{closure}}::hf7f4c21e0cce9605
                       at /checkout/src/libstd/panicking.rs:381
   3: 0x80129aa6 - std::panicking::default_hook::h0273df4f31ad7ce9
                       at /checkout/src/libstd/panicking.rs:397
   4: 0x8012a245 - std::panicking::rust_panic_with_hook::hb110eb893cf2f262
                       at /checkout/src/libstd/panicking.rs:577
   5: 0x8012a10a - std::panicking::begin_panic::hba4f7483f98fa441
                       at /checkout/src/libstd/panicking.rs:538
   6: 0x8012a026 - std::panicking::begin_panic_fmt::hf4a59e9c0b17558b
                       at /checkout/src/libstd/panicking.rs:522
   7: 0x80129f9b - rust_begin_unwind
                       at /checkout/src/libstd/panicking.rs:498
   8: 0x8017728e - core::panicking::panic_fmt::h34d249fd2e4d796e
                       at /checkout/src/libcore/panicking.rs:71
   9: 0x8017717c - core::panicking::panic::h912f4f8254e1a3ab
                       at /checkout/src/libcore/panicking.rs:51
  10: 0x800f923c - brotli::enc::backward_references::TestStaticDictionaryItem::h8e3ceceaf96520b2
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1131
  11: 0x80042d3e - brotli::enc::backward_references::SearchInStaticDictionary::hbe772f9a65587fc3
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1171
  12: 0x80035f59 -  as brotli::enc::backward_references::AnyHasher>::FindLongestMatch::h0b8eb4ddd2cce0b7
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:997
  13: 0x8003e19c - brotli::enc::backward_references::CreateBackwardReferences::he3119ac7c3437ed4
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1348
  14: 0x8004458d - brotli::enc::backward_references::BrotliCreateBackwardReferences::h4ce86d42244db8fa
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/backward_references.rs:1535
  15: 0x80087f11 - brotli::enc::encode::EncodeData::h2155e11331a85a0b
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/encode.rs:2799
  16: 0x800907c1 - brotli::enc::encode::BrotliEncoderCompressStream::hc8b4e371187e8bca
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/encode.rs:3366
  17: 0x800b082d - brotli::enc::BrotliCompressCustomIo::hbb4c34f675cafcbe
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/mod.rs:240
  18: 0x800b12c3 - brotli::enc::BrotliCompressCustomAlloc::h2dfef9c4c5059e19
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/mod.rs:138
  19: 0x800b0184 - brotli::enc::BrotliCompress::he08961ea1a50f683
                       at /home/osboxes/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-1.1.0/src/enc/mod.rs:65
  20: 0x800e831f - test_brotli_32bit_target::main::hf8054a0ec07e1298
                       at src/main.rs:21
  21: 0x800e8212 - std::rt::lang_start::{{closure}}::he8b899603e478150
                       at /checkout/src/libstd/rt.rs:74
  22: 0x8012f97c - std::sys_common::backtrace::__rust_begin_short_backtrace::h72d10003122a0a61
                       at /checkout/src/libstd/rt.rs:59
                       at /checkout/src/libstd/sys_common/backtrace.rs:133
  23: 0x80129f52 - std::panicking::try::do_call::hb55332b2ef16d564
                       at /checkout/src/libstd/rt.rs:59
                       at /checkout/src/libstd/panicking.rs:480
  24: 0x8013d2d2 - __rust_maybe_catch_panic
                       at /checkout/src/libpanic_unwind/lib.rs:101
  25: 0x8012cf65 - std::rt::lang_start_internal::h2cf06419fef56d5f
                       at /checkout/src/libstd/panicking.rs:459
                       at /checkout/src/libstd/panic.rs:365
                       at /checkout/src/libstd/rt.rs:58
  26: 0x800e81e1 - std::rt::lang_start::h2e896fbd6e6fa04c
                       at /checkout/src/libstd/rt.rs:74
  27: 0x800e878a - main
  28: 0xb758f275 - __libc_start_main
  29: 0x80010c4d - 
    
  

Can't build `c` drop-in replacement

➜  rust-brotli git:(master) ✗ cd c && make
cargo build
   Compiling brotli-ffi v1.1.1 (/home/mkpankov/work/rust-brotli/c)
error[E0433]: failed to resolve: could not find `ffi` in `brotli`
 --> src/lib.rs:8:17
  |
8 | pub use brotli::ffi::compressor::*;
  |                 ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
 --> src/lib.rs:9:17
  |
9 | pub use brotli::ffi::multicompress::*;
  |                 ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:10:17
   |
10 | pub use brotli::ffi::decompressor::*;
   |                 ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:14:21
   |
14 |     let _ = brotli::ffi::decompressor::CBrotliDecoderDecompress(0, null_mut(), null_mut(), null_mut());
   |                     ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:23:25
   |
23 |         let _ = brotli::ffi::compressor::BrotliEncoderVersion();
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:24:25
   |
24 |         let _ = brotli::ffi::decompressor::CBrotliDecoderCreateInstance(None, None, null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:25:25
   |
25 | ...   let _ = brotli::ffi::decompressor::CBrotliDecoderSetParameter(null_mut(), brotli::ffi::decompressor::ffi::interface::BrotliDecoderP...
   |                       ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:25:91
   |
25 | ...   let _ = brotli::ffi::decompressor::CBrotliDecoderSetParameter(null_mut(), brotli::ffi::decompressor::ffi::interface::BrotliDecoderP...
   |                                                                                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:26:25
   |
26 | ...   let _ = brotli::ffi::decompressor::CBrotliDecoderDecompressStream(null_mut(), null_mut(), null_mut(), null_mut(), null_mut(), null_...
   |                       ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:28:25
   |
28 |         let _ = brotli::ffi::decompressor::CBrotliDecoderMallocU8(null_mut(), 0);
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:29:25
   |
29 |         let _ = brotli::ffi::decompressor::CBrotliDecoderMallocUsize(null_mut(), 0);
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:30:25
   |
30 |         let _ = brotli::ffi::decompressor::CBrotliDecoderFreeU8(null_mut(), null_mut(), 0);
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:31:25
   |
31 |         let _ = brotli::ffi::decompressor::CBrotliDecoderFreeUsize(null_mut(), null_mut(), 0);
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:32:25
   |
32 |         let _ = brotli::ffi::decompressor::CBrotliDecoderDestroyInstance(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:33:25
   |
33 |         let _ = brotli::ffi::decompressor::CBrotliDecoderHasMoreOutput(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:34:25
   |
34 |         let _ = brotli::ffi::decompressor::CBrotliDecoderTakeOutput(null_mut(), null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:35:25
   |
35 |         let _ = brotli::ffi::decompressor::CBrotliDecoderIsUsed(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:36:25
   |
36 |         let _ = brotli::ffi::decompressor::CBrotliDecoderIsFinished(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:37:25
   |
37 |         let _ = brotli::ffi::decompressor::CBrotliDecoderGetErrorCode(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:38:25
   |
38 |         let _ = brotli::ffi::decompressor::CBrotliDecoderGetErrorString(null_mut());
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:39:25
   |
39 |         let _ = brotli::ffi::decompressor::CBrotliDecoderErrorString(
   |                         ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: could not find `ffi` in `brotli`
  --> src/lib.rs:40:21
   |
40 |             brotli::ffi::decompressor::ffi::BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_UNREACHABLE);
   |                     ^^^ could not find `ffi` in `brotli`

error[E0433]: failed to resolve: use of undeclared type `BrotliEncoderMode`
  --> src/lib.rs:49:43
   |
49 |         let _ = BrotliEncoderCompress(0,0,BrotliEncoderMode::BROTLI_MODE_GENERIC, 0, null_mut(), null_mut(), null_mut());
   |                                           ^^^^^^^^^^^^^^^^^ use of undeclared type `BrotliEncoderMode`

error[E0433]: failed to resolve: use of undeclared type `BrotliEncoderOperation`
  --> src/lib.rs:50:57
   |
50 | ...   let _ = BrotliEncoderCompressStream(null_mut(), BrotliEncoderOperation::BROTLI_OPERATION_FINISH, null_mut(), null_mut(), null_mut()...
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `BrotliEncoderOperation`

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCreateInstance` in this scope
  --> src/lib.rs:41:17
   |
41 |         let _ = BrotliEncoderCreateInstance(None, None, null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderCreateInstance;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderSetParameter` in this scope
  --> src/lib.rs:42:17
   |
42 |         let _ = BrotliEncoderSetParameter(null_mut(), brotli::enc::encode::BrotliEncoderParameter::BROTLI_PARAM_MODE, 0);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::BrotliEncoderSetParameter;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderDestroyInstance` in this scope
  --> src/lib.rs:43:17
   |
43 |         let _ = BrotliEncoderDestroyInstance(null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderDestroyInstance;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderIsFinished` in this scope
  --> src/lib.rs:44:17
   |
44 |         let _ = BrotliEncoderIsFinished(null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderIsFinished;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderHasMoreOutput` in this scope
  --> src/lib.rs:45:17
   |
45 |         let _ = BrotliEncoderHasMoreOutput(null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderHasMoreOutput;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderTakeOutput` in this scope
  --> src/lib.rs:46:17
   |
46 |         let _ = BrotliEncoderTakeOutput(null_mut(), null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderTakeOutput;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderMaxCompressedSize` in this scope
  --> src/lib.rs:47:17
   |
47 |         let _ = BrotliEncoderMaxCompressedSize(0);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::BrotliEncoderMaxCompressedSize;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderSetCustomDictionary` in this scope
  --> src/lib.rs:48:17
   |
48 |         let _ = BrotliEncoderSetCustomDictionary(null_mut(), 0, null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::encode::BrotliEncoderSetCustomDictionary;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCompress` in this scope
   --> src/lib.rs:49:17
    |
49  |           let _ = BrotliEncoderCompress(0,0,BrotliEncoderMode::BROTLI_MODE_GENERIC, 0, null_mut(), null_mut(), null_mut());
    |                   ^^^^^^^^^^^^^^^^^^^^^
    |
   ::: /home/mkpankov/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-3.3.2/src/enc/mod.rs:139:1
    |
139 | / pub fn BrotliCompress<InputType, OutputType>(r: &mut InputType,
140 | |                                              w: &mut OutputType,
141 | |                                              params: &BrotliEncoderParams)
142 | |                                                -> Result<usize, io::Error>
143 | |   where InputType: Read,
144 | |         OutputType: Write
    | |_________________________- similarly named function `BrotliCompress` defined here
    |
help: a function with a similar name exists
    |
49  |         let _ = BrotliCompress(0,0,BrotliEncoderMode::BROTLI_MODE_GENERIC, 0, null_mut(), null_mut(), null_mut());
    |                 ^^^^^^^^^^^^^^
help: consider importing this function
    |
7   | use enc::encode::BrotliEncoderCompress;
    |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCompressStream` in this scope
    --> src/lib.rs:50:17
     |
50   |   ...   let _ = BrotliEncoderCompressStream(null_mut(), BrotliEncoderOperation::BROTLI_OPERATION_FINISH, null_mut(), null_mut(), null_mut()...
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
    ::: /home/mkpankov/.cargo/registry/src/github.com-1ecc6299db9ec823/brotli-decompressor-2.3.2/src/decode.rs:2643:1
     |
2643 | / pub fn BrotliDecompressStream<AllocU8: alloc::Allocator<u8>,
2644 | |                               AllocU32: alloc::Allocator<u32>,
2645 | |                               AllocHC: alloc::Allocator<HuffmanCode>>
2646 | |   (available_in: &mut usize,
...    |
2653 | |    mut s: &mut BrotliState<AllocU8, AllocU32, AllocHC>)
2654 | |    -> BrotliResult {
     | |__________________- similarly named function `BrotliDecompressStream` defined here
     |
help: a function with a similar name exists
     |
50   |         let _ = BrotliDecompressStream(null_mut(), BrotliEncoderOperation::BROTLI_OPERATION_FINISH, null_mut(), null_mut(), null_mut(), null_mut(), null_mut());
     |                 ^^^^^^^^^^^^^^^^^^^^^^
help: consider importing this function
     |
7    | use enc::encode::BrotliEncoderCompressStream;
     |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderMallocU8` in this scope
  --> src/lib.rs:51:17
   |
51 |         let _ = BrotliEncoderMallocU8(null_mut(), 0);
   |                 ^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderFreeU8` in this scope
  --> src/lib.rs:52:17
   |
52 |         let _ = BrotliEncoderFreeU8(null_mut(), null_mut(), 0);
   |                 ^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderMallocUsize` in this scope
  --> src/lib.rs:53:17
   |
53 |         let _ = BrotliEncoderMallocUsize(null_mut(), 0);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderFreeUsize` in this scope
  --> src/lib.rs:54:17
   |
54 |         let _ = BrotliEncoderFreeUsize(null_mut(), null_mut(), 0);
   |                 ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderMaxCompressedSizeMulti` in this scope
  --> src/lib.rs:55:17
   |
55 |         let _ = BrotliEncoderMaxCompressedSizeMulti(0,0);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
7  | use enc::BrotliEncoderMaxCompressedSizeMulti;
   |

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCompressMulti` in this scope
  --> src/lib.rs:56:17
   |
56 |         let _ = BrotliEncoderCompressMulti(0,null_mut(), null_mut(), 0, null_mut(), null_mut(), null_mut(), 0, None, None, null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCreateWorkPool` in this scope
  --> src/lib.rs:57:17
   |
57 |         let _ = BrotliEncoderCreateWorkPool(0, None, None, null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderDestroyWorkPool` in this scope
  --> src/lib.rs:58:17
   |
58 |         let _ = BrotliEncoderDestroyWorkPool(null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `BrotliEncoderCompressWorkPool` in this scope
  --> src/lib.rs:59:17
   |
59 | ...   let _ = BrotliEncoderCompressWorkPool(null_mut(), 0, null_mut(), null_mut(), 0, null_mut(), null_mut(), null_mut(), 0 ,None, None, ...
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `brotli-ffi` due to 43 previous errors
make: *** [Makefile:31: target/debug/libbrotli.so] Error 101
➜  c git:(master) ✗ rustc --version
rustc 1.55.0 (c8dfcfe04 2021-09-06)

simd feature doesn't compile

Problem

The simd feature doesn't compile because of an error in packed_simd.

Steps to reproduce

Add dependency brotli with simd feature to any crate.

Solution

Switching to packed_simd_2 is probably the solution.

Details

Tested with Rust stable 1.54.0 and nightly 1.56.0 (2021-07-28), on Linux 5.10.52-1-lts.

Code style

Hey team,

first of all, awesome work! I don't know if this is a bug or accidental, but there's some code style issues with the crate, these functions use CamelCase rather than underscore_case as functions should in Rust (to distinguish them from type names, such as structs, enums, and traits):

Is this intentional or would it be possible to fix it for an upcoming major release? I understand if it is a deliberate design choice, but it would fit in better with the Rust ecosystem if these matched the established style.

Also, in general I notice that the code base seems to be in desperate need of some "cargo fmt". Is this something that is intentionally not done?

Thanks for the great work,
-Patrick

Crash when compressing file with -q0

breaks-brotli.gz

Download the attached file then do

$ gunzip breaks-brotli.gz
$ RUST_BACKTRACE=1 cargo run --release --bin brotli -- -c -q0 breaks-brotli compressed
    Finished release [optimized] target(s) in 0.06s
     Running `target/release/brotli -c -q0 breaks-brotli compressed`
thread 'main' panicked at 'range start index 89173 out of range for slice of length 65536', /home/aidanhs/work/rust-brotli/src/enc/compress_fragment.rs:939:29
stack backtrace:
   0: rust_begin_unwind
             at /rustc/399ba6bb377ce02224b57c4d6e127e160fa76b34/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/399ba6bb377ce02224b57c4d6e127e160fa76b34/library/core/src/panicking.rs:107:14
   2: core::slice::index::slice_start_index_len_fail
             at /rustc/399ba6bb377ce02224b57c4d6e127e160fa76b34/library/core/src/slice/index.rs:35:5
   3: brotli::enc::compress_fragment::BrotliCompressFragmentFast
   4: brotli::enc::encode::BrotliEncoderCompressStreamFast
   5: brotli::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace

Full examples/doc would be useful

I'm currently attempting to use this library and I admit that I am at a loss.

A full example of a command-line brotli encoder/decoder would be nice, for instance.

`flush()` is unexpectedly panicking

The following program panics on Rust 1.26.1 using brotli 2.2.1:

extern crate brotli;

use std::io::{self, Write};

fn main() {
    let stdout = &mut io::stdout();
    let mut writer = brotli::CompressorWriter::new(stdout, 4096, 5, 22);
    let data = b"0123456789";

    writer.write_all(data).unwrap();
    writer.flush().unwrap();

    // the next write will panic
    writer.write_all(data).unwrap();
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidData, error: StringError("Invalid Data") }', libcore/result.rs:945:5

I am not sure whether or not there is a fix for this; I do not know enough about the brotli internals (compression algorithm or crate), but the flush behavior is very confusing. Barring an actual output failure, I would assume that most users will not associate flush() after a successful write_all() with a likely panic.

Any use of CompressorWriter::flush() as implemented right now could probably be replaced with mem::drop, which would be better as it prevents a panic from calling write_all() again at compile time.

If the codec does not allow partial flushing, I believe flush() should be a no-op. On the other hand, if it possible, I would very much like to use it in my use-case, which is streaming packets over TCP, flushing at each packet boundary to ensure they arrive in a timely manner.

Create tags for releases

This crates feels a bit abandoned, it would be nice if tags were created for released so we can at least check the diff between version since there is no changelog.

Compression mishandles errors from underlying reader

I was using this library with a wrapped reader that can timeout to bound search time for a best compression algorithm. The reader returns an Error(ErrorKind::TimedOut) but brotli doesn't report it. I was looking at the code and it appears that https://github.com/dropbox/rust-brotli/blob/master/src/enc/mod.rs#L249 doesn't follow the contract of readers. The only error that is ignorable is an interrupt, but all errors are ignored and the stream happily closes even though it's only read like 2% of the data. Needless to say this makes it impossible to get the original data back when the BrotliCompress function returns Ok(_).

No --appendable code exists inside brotli.c

Doc says "Additionally the CATABLE and APPENDABLE options are exposed..." except only the option --catable is exists in the brotli.c file - no "appendable". (also, note, appendable is spelled wrongly, apendable, in some places)

Also, it says "Specifically CATABLE files can be concatenated in any order" ... however - this test simply omits anything appended:

ls | ./brotli_tool --catable > outac.br ; pwd | ./brotli_tool --catable >> outac.br ; cat outac.br | ./decompressor | tail

(and, for what it's worth, "cat outac.br | brotli -d" reports "corrupt input [con]")

Unnecessary loop

'continue30: loop {

This loop continue30 is unnecessary because it will eventually break at line 1018. If we remove this loop and change all the break 'continue30; into continue and change all the break 'break29; into break, the execution time will decreased from 3.76s to 3.43s based on my test, which is a 1.1x speedup.

Hope this information helps!

drop in replacement of brotli, how so?

on arch linux e.g. brotli consists of the following:

❯ paru -Ql brotli
brotli /usr/
brotli /usr/bin/
brotli /usr/bin/brotli
brotli /usr/include/
brotli /usr/include/brotli/
brotli /usr/include/brotli/decode.h
brotli /usr/include/brotli/encode.h
brotli /usr/include/brotli/port.h
brotli /usr/include/brotli/types.h
brotli /usr/lib/
brotli /usr/lib/libbrotlicommon-static.a
brotli /usr/lib/libbrotlicommon.so
brotli /usr/lib/libbrotlicommon.so.1
brotli /usr/lib/libbrotlicommon.so.1.0.9
brotli /usr/lib/libbrotlidec-static.a
brotli /usr/lib/libbrotlidec.so
brotli /usr/lib/libbrotlidec.so.1
brotli /usr/lib/libbrotlidec.so.1.0.9
brotli /usr/lib/libbrotlienc-static.a
brotli /usr/lib/libbrotlienc.so
brotli /usr/lib/libbrotlienc.so.1
brotli /usr/lib/libbrotlienc.so.1.0.9
brotli /usr/lib/pkgconfig/
brotli /usr/lib/pkgconfig/libbrotlicommon.pc
brotli /usr/lib/pkgconfig/libbrotlidec.pc
brotli /usr/lib/pkgconfig/libbrotlienc.pc

removing brotli is not possible as there are dependencies:

❯ paru -Rs brotli
checking dependencies...
error: failed to prepare transaction (could not satisfy dependencies)
:: removing brotli breaks dependency 'brotli' required by android-tools
:: removing brotli breaks dependency 'brotli' required by chromium
:: removing brotli breaks dependency 'brotli' required by curl
:: removing brotli breaks dependency 'libbrotlidec.so=1-64' required by curl
:: removing brotli breaks dependency 'brotli' required by freetype2
:: removing brotli breaks dependency 'brotli' required by gnutls
:: removing brotli breaks dependency 'brotli' required by libjxl
:: removing brotli breaks dependency 'brotli' required by libsoup
:: removing brotli breaks dependency 'libbrotlidec.so=1-64' required by libsoup
:: removing brotli breaks dependency 'brotli' required by libsoup3
:: removing brotli breaks dependency 'libbrotlidec.so=1-64' required by libsoup3
:: removing brotli breaks dependency 'brotli' required by nodejs
:: removing brotli breaks dependency 'brotli' required by qt6-base
:: removing brotli breaks dependency 'brotli' required by woff2

rust-brotli currently is the following, binary brotli renamed to brotlir at the moment to not clash with brotli:

❯ paru -Ql rust-brotli
rust-brotli /usr/
rust-brotli /usr/bin/
rust-brotli /usr/bin/brotlir
rust-brotli /usr/bin/catbrotli

what and how one would install rust-brotli to drop in instead of the shared libs as well? would it mean to link the rust-brotli so to all of the ones wanted?

./target/release/libbrotli_ffi.so

into_inner on Decompressor discards data due to buffering

Steps to reproduce:

  1. Decompress a Brotli stream from some input data.
  2. Call into_inner(), then read() the result to check if there is any remaining unread input data (for instance, extra junk at the end of the compressed stream).

Expected result:

If there is unread input data, it is readable.

Actual result:

If there is unread input data, it may or may not be available after calling into_inner(), depending on whether it was in the buffer or not.

Proposed fix:

If a fix for #83 is implemented, Decompressor will have the property that reading Ok(0) from it means the entire input data was consumed. In that situation, into_inner() can safely be called. Decompressor's into_inner() could be documented to only be safe after reading Ok(0) from Decompressor.

This would be useful in the ureq HTTP client, where the inner reader might be a PoolReturnRead that returns a connection to a connection pool once a response body has been fully read. In that situation, we need to check for any unread bytes at the end of the response body, which could indicate a desynchronized HTTP connection that we need to drop.

Test code to reproduce:

    #[test]
    fn test_no_vanishing_bytes() {
        // Output from this command:
        // (brotli -c <<<"hello"; echo goodbye) | xxd -p | sed 's/../\\x&/g'
        let compressed_with_extra = b"\x8f\x02\x80\x68\x65\x6c\x6c\x6f\x0a\x03\x67\x6f\x6f\x64\x62\x79\x65\x0a";
        let mut cursor = Cursor::new(compressed_with_extra);
        let mut reader = brotli_decompressor::Decompressor::new(cursor, 8000);
        std::io::read_to_string(&mut reader).unwrap();
        let unwrapped_cursor = reader.into_inner();
        assert_eq!(std::io::read_to_string(unwrapped_cursor).unwrap(), "goodbye".to_string());
    }

Flushing sometimes leaves the compressor in an inconsistent state

Thanks for your work porting brotli to Rust :)

I've had an issue when using your crate, specifically when flushing streams: after a flush, all write operations would fail. This would only happen sometimes, depending on the number of bytes compressed so far, so it was pretty hard to track down.

I think I found the culprit: the flush_or_close() method used in the implementation of Write, when called to flush(), improperly stops calling the compressor without checking if there is more data to flush (since the first implementation in c1959ae)

The documentation on how to use BROTLI_OPERATION_FLUSH (https://brotli.org/encode.html#aed2 , https://brotli.org/encode.html#a512) mentions the compressor should be called until it has no available input data and BrotliEncoderHasMoreOutput() returns false:

	Under some circumstances (e.g. lack of output stream capacity) this operation would require several calls to BrotliEncoderCompressStream
	[...]
	Warning
	When flushing and finishing, op should not change until operation is complete; input stream should not be swapped, reduced or extended as well.

The current implementation calls BrotliEncoderCompressStream() once and always returns Ok(), which may leave the compressor in BROTLI_OPERATION_FLUSH state and makes future write operations return an Err() (and allow the caller to modify the input stream, leaving room for unexpected compression results).

I'm suggesting a patch in a tiny pull request, which (at least in all the usecases I've been able to reproduce sporadically), solves the issue.

Underflow when decoding

I haven't tried to reproduce this outside of Servo, but I encountered an underflow panic when decoding this block:

0x120212000: 0xf6a85570 0x8bd645bc 0x1d51a554 0x0946b6e8
0x120212010: 0x96a1ad87 0x7ac33fb9 0xa8c8bd29 0x9e0a67c6
0x120212020: 0xcffae1bb 0x64d36450 0xce9228d2 0x2b350265
0x120212030: 0x15d29a50 0x70b86308 0x23b2c500 0x1ec15282
0x120212040: 0x802b5eb0 0x058d5983 0x51be8b67 0xf6bf0138
0x120212050: 0x22156250 0x4a4aa6f6 0x264bdd17 0xb94586b4
0x120212060: 0x6c86f406 0x9e393040 0x7b94bab9 0x813578d3
0x120212070: 0x2300b954 0x27002700 0xc200523f 0x12604ff4
0x120212080: 0xbd590b8b 0x441f9cc3 0x5351dd64 0x516b53b3
0x120212090: 0xf5dd03dd 0x7322df1d 0xfe41cdcf 0xeadf4d49
0x1202120a0: 0x2c3e0a58 0xc7820dce 0x06c26253 0x2664946b
0x1202120b0: 0xd3a1639c 0x3271e76b 0x120d11ed 0x5c2ae75d
0x1202120c0: 0x21bd1122 0x8b840be1 0x06112334 0xe59756c5
0x1202120d0: 0xb4a54e1d 0xac45a996 0xb8e1895e 0x314d689f
0x1202120e0: 0xf0913c91 0xf1e324a9 0xdc5e8994 0xdfbfeea9
0x1202120f0: 0x648cdd4e 0x0bf815dd 0xb94dcb0f 0xc973d2c7
0x120212100: 0xac53d3d2 0x9e704816 0xf314e9c4 0x5e32c855
0x120212110: 0xa6d7813d 0x1339b0df 0x0afc79b2 0xc9109209
0x120212120: 0x8dc65170 0x1a4ce298 0x32ec4014 0x095f56e9
0x120212130: 0x491381a1 0xa32897ca 0xbc154bcf 0xe899853f
0x120212140: 0xe060fcf5 0x0cfaf39f 0xbfd774f9 0x3c745b04
0x120212150: 0x50ff6692 0x68299dfa 0x3d7b84d1 0x10acb294
0x120212160: 0x49260b55 0x4a2be7af 0x98c235ed 0xc90f5ec9
0x120212170: 0x275f1f54 0x47819df0 0xbd10af78 0x89cdc25e
0x120212180: 0x1efa0f0e 0x00befc26 0xe706183f 0xb5545e5c
0x120212190: 0x6f7c8a1b 0x9a320c30 0x93d2aac0 0x0f926631
0x1202121a0: 0xca7b4a78 0x0b02c819 0x59c3f877 0xd6ad8f39
0x1202121b0: 0x8de2c458 0x442ac45a 0x50acba6d 0xf6a43edd
0x1202121c0: 0xb116674a 0x530d1bd6 0x4cbaf77c 0xabfaa7db
0x1202121d0: 0x4d6b6914 0x9e37c149 0xc7960cb0 0x286954de
0x1202121e0: 0x0577c78e 0x40993b95 0x478e4303 0xe9591717
0x1202121f0: 0x8469d6b9 0xb1b56614 0x0abcb358 0x487af667
frame #7: 0x0000000101394086 servo`brotli::decode::ReadCodeLengthCodeLengths<alloc_no_stdlib::heap_alloc::HeapAlloc<u8>,alloc_no_stdlib::heap_alloc::HeapAlloc<u32>,alloc_no_stdlib::heap_alloc::HeapAlloc<brotli::huffman::HuffmanCode>>(s=0x000000013481e440, input=&[u8] at 0x000000013481bfa0) + 1622 at decode.rs:761
   758 	    fast_mut!((s.code_length_code_lengths)[code_len_idx as usize]) = v as u8;
   759 	    BROTLI_LOG_ARRAY_INDEX!(s.code_length_code_lengths, code_len_idx);
   760 	    if v != 0 {
-> 761 	      space -= (32 >> v);
   762 	      num_codes += 1;
   763 	      fast_mut!((s.code_length_histo)[v as usize]) += 1;
   764 	      if space.wrapping_sub(1) >= 32 {
(lldb) p space
(unsigned int) $15 = 1
(lldb) p v
(unsigned int) $16 = 2

Make a reusable Python package, and publish to PyPI

What an incredibly useful library!

Seeing how there's already the Python bindings, maybe it's possible to package and put on PyPI?

In case it's already there, please disregard — I tried search, to no avail.

3.3.4 cannot be built on stable release channel

tried to create a package for arch linux. stable channel did not work, so i used unstable, and got the following:

cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
cargo build --frozen --release
error: the lock file <...>src/rust-brotli-3.3.4/Cargo.lock needs to be updated but --locked was passed to prevent this
error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/rt/.cargo/registry/src/github.com-1ecc6299db9ec823/packed_simd_2-0.3.8/src/lib.rs:214:1
    |
214 | / #![feature(
215 | |     adt_const_params,
216 | |     repr_simd,
217 | |     rustc_attrs,
...   |
224 | |     custom_inner_attributes,
225 | | )]
    | |__^

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/rt/.cargo/registry/src/github.com-1ecc6299db9ec823/packed_simd_2-0.3.8/src/lib.rs:219:5
    |
219 |     stdsimd,
    |     ^^^^^^^

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/rt/.cargo/registry/src/github.com-1ecc6299db9ec823/packed_simd_2-0.3.8/src/lib.rs:222:5
    |
222 |     core_intrinsics,
    |     ^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0554`.
error: could not compile `packed_simd_2` due to 3 previous errors
==> ERROR: A failure occurred in check().

Behavioral difference between google/brotli and dropbox/rust-brotli

I've been tinkering with replacing brotli with rust-brotli, and I've hit an interesting behavioral difference. The included C++ program works correctly when using the C brotli implementation, but segfaults with the Rust one:

#include <fstream>
#include <iostream>
#include <streambuf>
#include <string>
#include <string_view>

#include "brotli/encode.h"

int main(int argc, char** argv) {
  if (argc < 2) {
    std::cerr << "pass a file to compress" << std::endl;
    return 1;
  }
  std::string path = argv[1];
  std::cout << "attempting to brotli-ize " << path << std::endl;

  std::ifstream input_file(path);
  std::string data((std::istreambuf_iterator<char>(input_file)),
                   std::istreambuf_iterator<char>());
  std::string_view dv(data);

  auto* state = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
  if (state == nullptr) {
    std::cerr << "failed to make brotli encoder" << std::endl;
    return 1;
  }
  if (!BrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT,
                                 dv.size())) {
    std::cerr << "failed to give brotli a size hint" << std::endl;
    return 1;
  }
  size_t in_left, out_left, written = 0;
  BROTLI_BOOL result = BROTLI_TRUE;
  while (dv.size() && result) {
    in_left = dv.size();
    out_left = 0;
    const uint8_t* next_in = reinterpret_cast<const uint8_t*>(dv.data());
    std::cout << "attempt to compress " << dv.size() << std::endl;
    result =
        BrotliEncoderCompressStream(state, BROTLI_OPERATION_PROCESS, &in_left,
                                    &next_in, &out_left, nullptr, nullptr);
    size_t buffer_size = 0;
    /*const uint8_t* buf = */ BrotliEncoderTakeOutput(state, &buffer_size);
    if (buffer_size) {
      written += buffer_size;
    }
    dv.remove_prefix(dv.size() - in_left);
  }
  while (result && !BrotliEncoderIsFinished(state)) {
    in_left = 0;
    out_left = 0;
    const uint8_t* next_in = nullptr;
    result = BrotliEncoderCompressStream(
        state, BROTLI_OPERATION_FINISH, &in_left, &next_in,
        &out_left, nullptr, nullptr);
    size_t buffer_size = 0;
    /*const uint8_t* buffer = */BrotliEncoderTakeOutput(state, &buffer_size);
    if (buffer_size > 0) {
      written += buffer_size;
    }
  }
  BrotliEncoderDestroyInstance(state);
  std::cout << "brotli'd down to " << written << " bytes" << std::endl;
  return 0;
}

I'm not familiar enough with the internals of rust-brotli to figure this out quickly, but I was hoping by filing a bug with a reduced test case might help someone figure this out. I think this might be related to #44, but I don't appear to need multiple chunks to trigger the segfault. As far as I can tell, the way this test program uses brotli is supported per the comments in encode.h, so I assume that the crasher in Rust is a bug of missing functionality and not merely a guard against an unexpected NULL.

Provide Rust only interface

Having the C FFI interface exported via no_mangle functions when brotli is used as an rlib dependency causes issues when linking into a project that also depends on the C brotli library (see Nullus157/async-compression#83).

I'm not sure what the best approach for this would be; as someone that has not worked on a library exposing a C ABI, it seems to me that this would work better as a separate crate simply wrapping a Rustic implementation, instead of being combined into a single crate. Another idea I had was putting the ffi module behind a cargo feature. But neither of these feel like the perfect solution to me.

BSD or MIT

Hello, Cargo.toml lists BSD OR MIT, however LICENSE file contains only info about BSD... Who is right?

Performance metrics

Hi, thanks for the awesome implementation (I esp liked the ability to concatenate, and I wish it would become a core standard without the extra flags). Are there any performance metrics comparing the google's implementation with yours? Thx!

Mode and maybe other parameters in CompressorReader struct

Hello.

Currently the CompressorReader struct only accepts quality and lg_window_size as Brotli parameters. Nevertheless, other parameters like the mode (BrotliEncoderMode::BROTLI_MODE_TEXT or BrotliEncoderMode::BROTLI_MODE_FONT) would be desirable.

Other structs like BrotliCompress accept the fully customizable BrotliEncoderParams struct, this would be a good solution.

Regards.

Multithreaded compression

It was mentioned in the announcement that "Multithreaded compression allows multiple threads to operate in unison on a single file." However, I've been struggling to find any documentation or examples that illustrate this feature. I would greatly appreciate it if someone could share a code snippet or example showing how to utilize this new functionality.
I suspect it is compress_multi, but the last parameter alloc_per_thread is unclear for me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.