about summary refs log tree commit diff
path: root/src/libflate
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-01-24 21:00:31 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-01-26 15:42:15 -0800
commitcdfdc1eb6b9ff58b4a264d1c112dfcbf6e9187ae (patch)
tree648f2dad8b0b1d0a079a569deaf304e241b15512 /src/libflate
parent26114838944128ffe66d1e9fc897cb45b1a5eb1d (diff)
downloadrust-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.rs133
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);
+    }
+}