(index<- ) ./libflate/lib.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Sat Apr 19 11:22:39 2014
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12
13 Simple compression
14
15 */
16
17 #![crate_id = "flate#0.11-pre"]
18 #![crate_type = "rlib"]
19 #![crate_type = "dylib"]
20 #![license = "MIT/ASL2"]
21 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
22 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
23 html_root_url = "http://static.rust-lang.org/doc/master")]
24 #![feature(phase)]
25 #![deny(deprecated_owned_vector)]
26
27 #[cfg(test)] #[phase(syntax, link)] extern crate log;
28
29 extern crate libc;
30
31 use std::c_vec::CVec;
32 use libc::{c_void, size_t, c_int};
33
34
35 pub mod rustrt {
36 use libc::{c_void, size_t, c_int};
37 #[link(name = "miniz", kind = "static")]
38 extern {
39 pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
40 src_buf_len: size_t,
41 pout_len: *mut size_t,
42 flags: c_int)
43 -> *mut c_void;
44
45 pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void,
46 src_buf_len: size_t,
47 pout_len: *mut size_t,
48 flags: c_int)
49 -> *mut c_void;
50 }
51 }
52
53 static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal"
54 static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
55 static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
56
57 fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
58 unsafe {
59 let mut outsz : size_t = 0;
60 let res = rustrt::tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void,
61 bytes.len() as size_t,
62 &mut outsz,
63 flags);
64 if !res.is_null() {
65 Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res)))
66 } else {
67 None
68 }
69 }
70 }
71
72 pub fn deflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
73 deflate_bytes_internal(bytes, LZ_NORM)
74 }
75
76 pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
77 deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
78 }
79
80 fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
81 unsafe {
82 let mut outsz : size_t = 0;
83 let res = rustrt::tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void,
84 bytes.len() as size_t,
85 &mut outsz,
86 flags);
87 if !res.is_null() {
88 Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res)))
89 } else {
90 None
91 }
92 }
93 }
94
95 pub fn inflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
96 inflate_bytes_internal(bytes, 0)
97 }
98
99 pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
100 inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
101 }
102
103 #[cfg(test)]
104 mod tests {
105 extern crate rand;
106
107 use super::{inflate_bytes, deflate_bytes};
108 use self::rand::Rng;
109
110 #[test]
111 #[allow(deprecated_owned_vector)]
112 fn test_flate_round_trip() {
113 let mut r = rand::task_rng();
114 let mut words = vec!();
115 for _ in range(0, 20) {
116 let range = r.gen_range(1u, 10);
117 words.push(r.gen_vec::<u8>(range));
118 }
119 for _ in range(0, 20) {
120 let mut input = vec![];
121 for _ in range(0, 2000) {
122 input.push_all(r.choose(words.as_slice()).as_slice());
123 }
124 debug!("de/inflate of {} bytes of random word-sequences",
125 input.len());
126 let cmp = deflate_bytes(input.as_slice()).expect("deflation failed");
127 let out = inflate_bytes(cmp.as_slice()).expect("inflation failed");
128 debug!("{} bytes deflated to {} ({:.1f}% size)",
129 input.len(), cmp.len(),
130 100.0 * ((cmp.len() as f64) / (input.len() as f64)));
131 assert_eq!(input.as_slice(), out.as_slice());
132 }
133 }
134
135 #[test]
136 fn test_zlib_flate() {
137 let bytes = vec!(1, 2, 3, 4, 5);
138 let deflated = deflate_bytes(bytes.as_slice()).expect("deflation failed");
139 let inflated = inflate_bytes(deflated.as_slice()).expect("inflation failed");
140 assert_eq!(inflated.as_slice(), bytes.as_slice());
141 }
142 }