Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag miniz_oxide as a #![no_std] library #81

Merged
merged 2 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion miniz_oxide/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@ exclude = ["benches/*", "tests/*"]
name = "miniz_oxide"

[dependencies]
adler32 = "1.0.4"
adler32 = { version = "1.1.0", default-features = false }

# Internal feature, only used when building as part of libstd, not part of the
# stable interface of this crate.
core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' }
alloc = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-alloc' }
compiler_builtins = { version = '0.1.2', optional = true }

[features]
# Internal feature, only used when building as part of libstd, not part of the
# stable interface of this crate.
rustc-dep-of-std = ['core', 'alloc', 'compiler_builtins', 'adler32/rustc-dep-of-std']
112 changes: 66 additions & 46 deletions miniz_oxide/src/deflate/core.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Streaming compression functionality.

use std::convert::TryInto;
use std::io::{self, Cursor, Seek, SeekFrom, Write};
use std::{cmp, mem};
use alloc::boxed::Box;
use core::convert::TryInto;
use core::{cmp, mem};

use super::super::*;
use super::deflate_flags::*;
Expand All @@ -14,6 +14,11 @@ use crate::deflate::buffer::{
use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER, MZ_ADLER32_INIT};
use crate::DataFormat;

// Currently not bubbled up outside this module, so can fill in with more
// context eventually if needed.
type Result<T, E = Error> = core::result::Result<T, E>;
struct Error {}

const MAX_PROBES_MASK: i32 = 0xFFF;

const MAX_SUPPORTED_HUFF_CODESIZE: usize = 32;
Expand Down Expand Up @@ -549,12 +554,12 @@ impl<'a> CallbackBuf<'a> {
.copy_from_slice(&params.local_buf.b[..n]);

params.out_buf_ofs += n;
if saved_output.pos != n as u64 {
if saved_output.pos != n {
params.flush_ofs = n as u32;
params.flush_remaining = (saved_output.pos - n as u64) as u32;
params.flush_remaining = (saved_output.pos - n) as u32;
}
} else {
params.out_buf_ofs += saved_output.pos as usize;
params.out_buf_ofs += saved_output.pos;
}

params.flush_remaining as i32
Expand Down Expand Up @@ -585,9 +590,9 @@ impl<'a> CallbackOut<'a> {
}
};

let cursor = Cursor::new(chosen_buffer);
OutputBufferOxide {
inner: cursor,
inner: chosen_buffer,
inner_pos: 0,
local: is_local,
bit_buffer: 0,
bits_in: 0,
Expand Down Expand Up @@ -649,7 +654,8 @@ impl<'a> CallbackOxide<'a> {
}

struct OutputBufferOxide<'a> {
pub inner: Cursor<&'a mut [u8]>,
pub inner: &'a mut [u8],
pub inner_pos: usize,
pub local: bool,

pub bit_buffer: u32,
Expand All @@ -662,25 +668,24 @@ impl<'a> OutputBufferOxide<'a> {
self.bit_buffer |= bits << self.bits_in;
self.bits_in += len;
while self.bits_in >= 8 {
let pos = self.inner.position();
self.inner.get_mut()[pos as usize] = self.bit_buffer as u8;
self.inner.set_position(pos + 1);
self.inner[self.inner_pos] = self.bit_buffer as u8;
self.inner_pos += 1;
self.bit_buffer >>= 8;
self.bits_in -= 8;
}
}

fn save(&self) -> SavedOutputBufferOxide {
SavedOutputBufferOxide {
pos: self.inner.position(),
pos: self.inner_pos,
bit_buffer: self.bit_buffer,
bits_in: self.bits_in,
local: self.local,
}
}

fn load(&mut self, saved: SavedOutputBufferOxide) {
self.inner.set_position(saved.pos);
self.inner_pos = saved.pos;
self.bit_buffer = saved.bit_buffer;
self.bits_in = saved.bits_in;
self.local = saved.local;
Expand All @@ -695,7 +700,7 @@ impl<'a> OutputBufferOxide<'a> {
}

struct SavedOutputBufferOxide {
pub pos: u64,
pub pos: usize,
pub bit_buffer: u32,
pub bits_in: u32,
pub local: bool,
Expand All @@ -712,17 +717,18 @@ impl BitBuffer {
self.bits_in += len;
}

fn flush(&mut self, output: &mut OutputBufferOxide) -> io::Result<()> {
let pos = output.inner.position() as usize;
fn flush(&mut self, output: &mut OutputBufferOxide) -> Result<()> {
let pos = output.inner_pos;
{
// isolation to please borrow checker
let inner = &mut (*output.inner.get_mut())[pos..pos + 8];
let inner = &mut output.inner[pos..pos + 8];
let bytes = u64::to_le_bytes(self.bit_buffer);
inner.copy_from_slice(&bytes);
}
output
.inner
.seek(SeekFrom::Current(i64::from(self.bits_in >> 3)))?;
match output.inner_pos.checked_add((self.bits_in >> 3) as usize) {
Some(n) if n <= output.inner.len() => output.inner_pos = n,
_ => return Err(Error {}),
}
self.bit_buffer >>= self.bits_in & !7;
self.bits_in &= 7;
Ok(())
Expand Down Expand Up @@ -760,19 +766,21 @@ struct RLE {
impl RLE {
fn prev_code_size(
&mut self,
packed_code_sizes: &mut Cursor<&mut [u8]>,
packed_code_sizes: &mut [u8],
packed_pos: &mut usize,
h: &mut HuffmanOxide,
) -> io::Result<()> {
) -> Result<()> {
let mut write = |buf| write(buf, packed_code_sizes, packed_pos);
let counts = &mut h.count[HUFF_CODES_TABLE];
if self.repeat_count != 0 {
if self.repeat_count < 3 {
counts[self.prev_code_size as usize] =
counts[self.prev_code_size as usize].wrapping_add(self.repeat_count as u16);
let code = self.prev_code_size;
packed_code_sizes.write_all(&[code, code, code][..self.repeat_count as usize])?;
write(&[code, code, code][..self.repeat_count as usize])?;
} else {
counts[16] = counts[16].wrapping_add(1);
packed_code_sizes.write_all(&[16, (self.repeat_count - 3) as u8][..])?;
write(&[16, (self.repeat_count - 3) as u8][..])?;
}
self.repeat_count = 0;
}
Expand All @@ -782,20 +790,22 @@ impl RLE {

fn zero_code_size(
&mut self,
packed_code_sizes: &mut Cursor<&mut [u8]>,
packed_code_sizes: &mut [u8],
packed_pos: &mut usize,
h: &mut HuffmanOxide,
) -> io::Result<()> {
) -> Result<()> {
let mut write = |buf| write(buf, packed_code_sizes, packed_pos);
let counts = &mut h.count[HUFF_CODES_TABLE];
if self.z_count != 0 {
if self.z_count < 3 {
counts[0] = counts[0].wrapping_add(self.z_count as u16);
packed_code_sizes.write_all(&[0, 0, 0][..self.z_count as usize])?;
write(&[0, 0, 0][..self.z_count as usize])?;
} else if self.z_count <= 10 {
counts[17] = counts[17].wrapping_add(1);
packed_code_sizes.write_all(&[17, (self.z_count - 3) as u8][..])?;
write(&[17, (self.z_count - 3) as u8][..])?;
} else {
counts[18] = counts[18].wrapping_add(1);
packed_code_sizes.write_all(&[18, (self.z_count - 11) as u8][..])?;
write(&[18, (self.z_count - 11) as u8][..])?;
}
self.z_count = 0;
}
Expand All @@ -804,6 +814,15 @@ impl RLE {
}
}

fn write(src: &[u8], dst: &mut [u8], dst_pos: &mut usize) -> Result<()> {
match dst.get_mut(*dst_pos..*dst_pos + src.len()) {
Some(s) => s.copy_from_slice(src),
None => return Err(Error {}),
}
*dst_pos += src.len();
Ok(())
}

impl Default for HuffmanOxide {
fn default() -> Self {
HuffmanOxide {
Expand Down Expand Up @@ -1036,7 +1055,7 @@ impl HuffmanOxide {
output.put_bits(0b01, 2)
}

fn start_dynamic_block(&mut self, output: &mut OutputBufferOxide) -> io::Result<()> {
fn start_dynamic_block(&mut self, output: &mut OutputBufferOxide) -> Result<()> {
// There will always be one, and only one end of block code.
self.count[0][256] = 1;

Expand Down Expand Up @@ -1075,35 +1094,35 @@ impl HuffmanOxide {

memset(&mut self.count[HUFF_CODES_TABLE][..MAX_HUFF_SYMBOLS_2], 0);

let mut packed_code_sizes_cursor = Cursor::new(&mut packed_code_sizes[..]);
let mut packed_pos = 0;
for &code_size in &code_sizes_to_pack[..total_code_sizes_to_pack] {
if code_size == 0 {
rle.prev_code_size(&mut packed_code_sizes_cursor, self)?;
rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
rle.z_count += 1;
if rle.z_count == 138 {
rle.zero_code_size(&mut packed_code_sizes_cursor, self)?;
rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
}
} else {
rle.zero_code_size(&mut packed_code_sizes_cursor, self)?;
rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
if code_size != rle.prev_code_size {
rle.prev_code_size(&mut packed_code_sizes_cursor, self)?;
rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
self.count[HUFF_CODES_TABLE][code_size as usize] =
self.count[HUFF_CODES_TABLE][code_size as usize].wrapping_add(1);
packed_code_sizes_cursor.write_all(&[code_size][..])?;
write(&[code_size], &mut packed_code_sizes, &mut packed_pos)?;
} else {
rle.repeat_count += 1;
if rle.repeat_count == 6 {
rle.prev_code_size(&mut packed_code_sizes_cursor, self)?;
rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
}
}
}
rle.prev_code_size = code_size;
}

if rle.repeat_count != 0 {
rle.prev_code_size(&mut packed_code_sizes_cursor, self)?;
rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
} else {
rle.zero_code_size(&mut packed_code_sizes_cursor, self)?;
rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
}

self.optimize_table(2, MAX_HUFF_SYMBOLS_2, 7, false);
Expand All @@ -1130,8 +1149,7 @@ impl HuffmanOxide {
}

let mut packed_code_size_index = 0 as usize;
let packed_code_sizes = packed_code_sizes_cursor.get_ref();
while packed_code_size_index < packed_code_sizes_cursor.position() as usize {
while packed_code_size_index < packed_pos {
let code = packed_code_sizes[packed_code_size_index] as usize;
packed_code_size_index += 1;
assert!(code < MAX_HUFF_SYMBOLS_2);
Expand Down Expand Up @@ -1474,7 +1492,7 @@ fn compress_lz_codes(
huff: &HuffmanOxide,
output: &mut OutputBufferOxide,
lz_code_buf: &[u8],
) -> io::Result<bool> {
) -> Result<bool> {
let mut flags = 1;
let mut bb = BitBuffer {
bit_buffer: u64::from(output.bit_buffer),
Expand Down Expand Up @@ -1573,7 +1591,7 @@ fn compress_block(
output: &mut OutputBufferOxide,
lz: &LZOxide,
static_block: bool,
) -> io::Result<bool> {
) -> Result<bool> {
if static_block {
huff.start_static_block(output);
} else {
Expand All @@ -1587,7 +1605,7 @@ fn flush_block(
d: &mut CompressorOxide,
callback: &mut CallbackOxide,
flush: TDEFLFlush,
) -> io::Result<i32> {
) -> Result<i32> {
let mut saved_buffer;
{
let mut output = callback
Expand Down Expand Up @@ -1635,7 +1653,7 @@ fn flush_block(
// (as literals are either 8 or 9 bytes), a raw block will
// never take up less space if the number of input bytes are less than 32.
let expanded = (d.lz.total_bytes > 32)
&& (output.inner.position() - saved_buffer.pos + 1 >= u64::from(d.lz.total_bytes))
&& (output.inner_pos - saved_buffer.pos + 1 >= (d.lz.total_bytes as usize))
&& (d.dict.lookahead_pos - d.dict.code_buf_dict_pos <= d.dict.size);

if use_raw_block || expanded {
Expand Down Expand Up @@ -2339,6 +2357,8 @@ mod test {
MZ_DEFAULT_WINDOW_BITS,
};
use crate::inflate::decompress_to_vec;
use std::prelude::v1::*;
use std::vec;

#[test]
fn u16_to_slice() {
Expand Down
6 changes: 5 additions & 1 deletion miniz_oxide/src/deflate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! This module contains functionality for compression.

use alloc::vec;
use alloc::vec::Vec;

mod buffer;
pub mod core;
pub mod stream;
Expand Down Expand Up @@ -119,7 +122,7 @@ fn compress_to_vec_inner(input: &[u8], level: u8, window_bits: i32, strategy: i3
// The comp flags function sets the zlib flag if the window_bits parameter is > 0.
let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy);
let mut compressor = CompressorOxide::new(flags);
let mut output = vec![0; std::cmp::max(input.len() / 2, 2)];
let mut output = vec![0; ::core::cmp::max(input.len() / 2, 2)];

let mut in_pos = 0;
let mut out_pos = 0;
Expand Down Expand Up @@ -157,6 +160,7 @@ fn compress_to_vec_inner(input: &[u8], level: u8, window_bits: i32, strategy: i3
mod test {
use super::{compress_to_vec, compress_to_vec_inner, CompressionStrategy};
use crate::inflate::decompress_to_vec;
use std::vec;

/// Test deflate example.
///
Expand Down
5 changes: 4 additions & 1 deletion miniz_oxide/src/deflate/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! As of now this is mainly inteded for use to build a higher-level wrapper.
//!
//! There is no DeflateState as the needed state is contained in the compressor struct itself.
use std::convert::{AsMut, AsRef};
use core::convert::{AsMut, AsRef};

use crate::deflate::core::{compress, CompressorOxide, TDEFLFlush, TDEFLStatus};
use crate::{MZError, MZFlush, MZStatus, StreamResult};
Expand Down Expand Up @@ -100,6 +100,9 @@ mod test {
use crate::deflate::CompressorOxide;
use crate::inflate::decompress_to_vec_zlib;
use crate::{MZFlush, MZStatus};
use std::prelude::v1::*;
use std::vec;

#[test]
fn test_state() {
let data = b"Hello zlib!";
Expand Down
Loading