diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-01-24 21:00:31 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-01-26 15:42:15 -0800 |
| commit | cdfdc1eb6b9ff58b4a264d1c112dfcbf6e9187ae (patch) | |
| tree | 648f2dad8b0b1d0a079a569deaf304e241b15512 /src/libflate | |
| parent | 26114838944128ffe66d1e9fc897cb45b1a5eb1d (diff) | |
| download | rust-cdfdc1eb6b9ff58b4a264d1c112dfcbf6e9187ae.tar.gz rust-cdfdc1eb6b9ff58b4a264d1c112dfcbf6e9187ae.zip | |
Move extra::flate to libflate
This is hopefully the beginning of the long-awaited dissolution of libextra. Using the newly created build infrastructure for building libraries, I decided to move the first module out of libextra. While not being a particularly meaty module in and of itself, the flate module is required by rustc and additionally has a native C dependency. I was able to very easily split out the C dependency from rustrt, update librustc, and magically everything gets installed to the right locations and built automatically. This is meant to be a proof-of-concept commit to how easy it is to remove modules from libextra now. I didn't put any effort into modernizing the interface of libflate or updating it other than to remove the one glob import it had.
Diffstat (limited to 'src/libflate')
| -rw-r--r-- | src/libflate/lib.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs new file mode 100644 index 00000000000..f746fe4ec32 --- /dev/null +++ b/src/libflate/lib.rs @@ -0,0 +1,133 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Simple compression + +*/ + +#[crate_id = "flate#0.10-pre"]; +#[crate_type = "rlib"]; +#[crate_type = "dylib"]; +#[license = "MIT/ASL2"]; +#[allow(missing_doc)]; + +use std::libc::{c_void, size_t, c_int}; +use std::libc; +use std::vec; + +pub mod rustrt { + use std::libc::{c_int, c_void, size_t}; + + #[link(name = "miniz", kind = "static")] + extern { + pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *c_void; + + pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *c_void; + } +} + +static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal" +static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum +static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum + +fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] { + unsafe { + let mut outsz : size_t = 0; + let res = rustrt::tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void, + bytes.len() as size_t, + &mut outsz, + flags); + assert!(res as int != 0); + let out = vec::raw::from_buf_raw(res as *u8, + outsz as uint); + libc::free(res as *mut c_void); + out + } +} + +pub fn deflate_bytes(bytes: &[u8]) -> ~[u8] { + deflate_bytes_internal(bytes, LZ_NORM) +} + +pub fn deflate_bytes_zlib(bytes: &[u8]) -> ~[u8] { + deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) +} + +fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] { + unsafe { + let mut outsz : size_t = 0; + let res = rustrt::tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void, + bytes.len() as size_t, + &mut outsz, + flags); + assert!(res as int != 0); + let out = vec::raw::from_buf_raw(res as *u8, + outsz as uint); + libc::free(res as *mut c_void); + out + } +} + +pub fn inflate_bytes(bytes: &[u8]) -> ~[u8] { + inflate_bytes_internal(bytes, 0) +} + +pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] { + inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) +} + +#[cfg(test)] +mod tests { + use super::{inflate_bytes, deflate_bytes}; + use std::rand; + use std::rand::Rng; + + #[test] + fn test_flate_round_trip() { + let mut r = rand::rng(); + let mut words = ~[]; + 20.times(|| { + let range = r.gen_range(1u, 10); + words.push(r.gen_vec::<u8>(range)); + }); + 20.times(|| { + let mut input = ~[]; + 2000.times(|| { + input.push_all(r.choose(words)); + }); + debug!("de/inflate of {} bytes of random word-sequences", + input.len()); + let cmp = deflate_bytes(input); + let out = inflate_bytes(cmp); + debug!("{} bytes deflated to {} ({:.1f}% size)", + input.len(), cmp.len(), + 100.0 * ((cmp.len() as f64) / (input.len() as f64))); + assert_eq!(input, out); + }); + } + + #[test] + fn test_zlib_flate() { + let bytes = ~[1, 2, 3, 4, 5]; + let deflated = deflate_bytes(bytes); + let inflated = inflate_bytes(deflated); + assert_eq!(inflated, bytes); + } +} |
