]> git.proxmox.com Git - rustc.git/blame - src/libflate/lib.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / libflate / lib.rs
CommitLineData
1a4d82fc
JJ
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//! Simple [DEFLATE][def]-based compression. This is a wrapper around the
12//! [`miniz`][mz] library, which is a one-file pure-C implementation of zlib.
13//!
14//! [def]: https://en.wikipedia.org/wiki/DEFLATE
15//! [mz]: https://code.google.com/p/miniz/
16
17#![crate_name = "flate"]
e9174d1e 18#![unstable(feature = "rustc_private", issue = "27812")]
1a4d82fc
JJ
19#![crate_type = "rlib"]
20#![crate_type = "dylib"]
e9174d1e 21#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
62682a34 22 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
92a42be0
SL
23 html_root_url = "https://doc.rust-lang.org/nightly/",
24 test(attr(deny(warnings))))]
7453a54e 25#![cfg_attr(not(stage0), deny(warnings))]
1a4d82fc 26
85aaf69f
SL
27#![feature(libc)]
28#![feature(staged_api)]
c34b1796 29#![feature(unique)]
54a0048b 30#![cfg_attr(test, feature(rustc_private, rand))]
85aaf69f 31
b039eaaf
SL
32#[cfg(test)]
33#[macro_use]
34extern crate log;
1a4d82fc
JJ
35
36extern crate libc;
37
38use libc::{c_void, size_t, c_int};
c34b1796 39use std::fmt;
1a4d82fc
JJ
40use std::ops::Deref;
41use std::ptr::Unique;
42use std::slice;
43
c34b1796
AL
44#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
45pub struct Error {
46 _unused: (),
47}
48
49impl Error {
50 fn new() -> Error {
b039eaaf 51 Error { _unused: () }
c34b1796
AL
52 }
53}
54
55impl fmt::Debug for Error {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 "decompression error".fmt(f)
58 }
59}
60
1a4d82fc
JJ
61pub struct Bytes {
62 ptr: Unique<u8>,
c34b1796 63 len: usize,
1a4d82fc
JJ
64}
65
66impl Deref for Bytes {
67 type Target = [u8];
68 fn deref(&self) -> &[u8] {
85aaf69f 69 unsafe { slice::from_raw_parts(*self.ptr, self.len) }
1a4d82fc
JJ
70 }
71}
72
73impl Drop for Bytes {
74 fn drop(&mut self) {
b039eaaf
SL
75 unsafe {
76 libc::free(*self.ptr as *mut _);
77 }
1a4d82fc
JJ
78 }
79}
80
81#[link(name = "miniz", kind = "static")]
7453a54e
SL
82#[cfg(not(cargobuild))]
83extern {}
84
85extern {
1a4d82fc
JJ
86 /// Raw miniz compression function.
87 fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
88 src_buf_len: size_t,
89 pout_len: *mut size_t,
90 flags: c_int)
91 -> *mut c_void;
92
93 /// Raw miniz decompression function.
94 fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
95 src_buf_len: size_t,
96 pout_len: *mut size_t,
97 flags: c_int)
98 -> *mut c_void;
99}
100
c34b1796
AL
101const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal"
102const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum
103const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum
1a4d82fc 104
c34b1796 105fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes {
1a4d82fc 106 unsafe {
c34b1796 107 let mut outsz: size_t = 0;
1a4d82fc
JJ
108 let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
109 bytes.len() as size_t,
110 &mut outsz,
111 flags);
c34b1796
AL
112 assert!(!res.is_null());
113 Bytes {
114 ptr: Unique::new(res as *mut u8),
115 len: outsz as usize,
1a4d82fc
JJ
116 }
117 }
118}
119
120/// Compress a buffer, without writing any sort of header on the output.
c34b1796 121pub fn deflate_bytes(bytes: &[u8]) -> Bytes {
1a4d82fc
JJ
122 deflate_bytes_internal(bytes, LZ_NORM)
123}
124
125/// Compress a buffer, using a header that zlib can understand.
c34b1796 126pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes {
1a4d82fc
JJ
127 deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
128}
129
b039eaaf 130fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes, Error> {
1a4d82fc 131 unsafe {
c34b1796 132 let mut outsz: size_t = 0;
1a4d82fc
JJ
133 let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
134 bytes.len() as size_t,
135 &mut outsz,
136 flags);
137 if !res.is_null() {
c34b1796
AL
138 Ok(Bytes {
139 ptr: Unique::new(res as *mut u8),
140 len: outsz as usize,
141 })
1a4d82fc 142 } else {
c34b1796 143 Err(Error::new())
1a4d82fc
JJ
144 }
145 }
146}
147
148/// Decompress a buffer, without parsing any sort of header on the input.
b039eaaf 149pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes, Error> {
1a4d82fc
JJ
150 inflate_bytes_internal(bytes, 0)
151}
152
153/// Decompress a buffer that starts with a zlib header.
b039eaaf 154pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes, Error> {
1a4d82fc
JJ
155 inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
156}
157
158#[cfg(test)]
159mod tests {
85aaf69f 160 #![allow(deprecated)]
1a4d82fc 161 use super::{inflate_bytes, deflate_bytes};
9346a6ac 162 use std::__rand::{thread_rng, Rng};
1a4d82fc
JJ
163
164 #[test]
165 fn test_flate_round_trip() {
9346a6ac 166 let mut r = thread_rng();
c34b1796 167 let mut words = vec![];
85aaf69f
SL
168 for _ in 0..20 {
169 let range = r.gen_range(1, 10);
1a4d82fc
JJ
170 let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
171 words.push(v);
172 }
85aaf69f 173 for _ in 0..20 {
1a4d82fc 174 let mut input = vec![];
85aaf69f 175 for _ in 0..2000 {
54a0048b 176 input.extend_from_slice(r.choose(&words).unwrap());
1a4d82fc
JJ
177 }
178 debug!("de/inflate of {} bytes of random word-sequences",
179 input.len());
c34b1796
AL
180 let cmp = deflate_bytes(&input);
181 let out = inflate_bytes(&cmp).unwrap();
1a4d82fc 182 debug!("{} bytes deflated to {} ({:.1}% size)",
b039eaaf
SL
183 input.len(),
184 cmp.len(),
1a4d82fc 185 100.0 * ((cmp.len() as f64) / (input.len() as f64)));
85aaf69f 186 assert_eq!(&*input, &*out);
1a4d82fc
JJ
187 }
188 }
189
190 #[test]
191 fn test_zlib_flate() {
c34b1796
AL
192 let bytes = vec![1, 2, 3, 4, 5];
193 let deflated = deflate_bytes(&bytes);
194 let inflated = inflate_bytes(&deflated).unwrap();
85aaf69f 195 assert_eq!(&*inflated, &*bytes);
1a4d82fc
JJ
196 }
197}