/src/libflate/lib.rs

https://gitlab.com/anispy211/rust · Rust · 135 lines · 103 code · 18 blank · 14 comment · 3 complexity · 84e112af261796d618d94c94ec06ead5 MD5 · raw file

  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 compression
  12. */
  13. #![crate_id = "flate#0.10-pre"]
  14. #![crate_type = "rlib"]
  15. #![crate_type = "dylib"]
  16. #![license = "MIT/ASL2"]
  17. #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
  18. html_favicon_url = "http://www.rust-lang.org/favicon.ico",
  19. html_root_url = "http://static.rust-lang.org/doc/master")]
  20. #![feature(phase)]
  21. #![deny(deprecated_owned_vector)]
  22. #[cfg(test)] #[phase(syntax, link)] extern crate log;
  23. use std::libc::{c_void, size_t, c_int};
  24. use std::libc;
  25. use std::c_vec::CVec;
  26. pub mod rustrt {
  27. use std::libc::{c_int, c_void, size_t};
  28. #[link(name = "miniz", kind = "static")]
  29. extern {
  30. pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
  31. src_buf_len: size_t,
  32. pout_len: *mut size_t,
  33. flags: c_int)
  34. -> *mut c_void;
  35. pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void,
  36. src_buf_len: size_t,
  37. pout_len: *mut size_t,
  38. flags: c_int)
  39. -> *mut c_void;
  40. }
  41. }
  42. static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal"
  43. static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
  44. static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
  45. fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> CVec<u8> {
  46. unsafe {
  47. let mut outsz : size_t = 0;
  48. let res = rustrt::tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void,
  49. bytes.len() as size_t,
  50. &mut outsz,
  51. flags);
  52. assert!(!res.is_null());
  53. CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))
  54. }
  55. }
  56. pub fn deflate_bytes(bytes: &[u8]) -> CVec<u8> {
  57. deflate_bytes_internal(bytes, LZ_NORM)
  58. }
  59. pub fn deflate_bytes_zlib(bytes: &[u8]) -> CVec<u8> {
  60. deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
  61. }
  62. fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> CVec<u8> {
  63. unsafe {
  64. let mut outsz : size_t = 0;
  65. let res = rustrt::tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void,
  66. bytes.len() as size_t,
  67. &mut outsz,
  68. flags);
  69. assert!(!res.is_null());
  70. CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))
  71. }
  72. }
  73. pub fn inflate_bytes(bytes: &[u8]) -> CVec<u8> {
  74. inflate_bytes_internal(bytes, 0)
  75. }
  76. pub fn inflate_bytes_zlib(bytes: &[u8]) -> CVec<u8> {
  77. inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
  78. }
  79. #[cfg(test)]
  80. mod tests {
  81. extern crate rand;
  82. use super::{inflate_bytes, deflate_bytes};
  83. use self::rand::Rng;
  84. #[test]
  85. #[allow(deprecated_owned_vector)]
  86. fn test_flate_round_trip() {
  87. let mut r = rand::task_rng();
  88. let mut words = vec!();
  89. for _ in range(0, 20) {
  90. let range = r.gen_range(1u, 10);
  91. words.push(r.gen_vec::<u8>(range));
  92. }
  93. for _ in range(0, 20) {
  94. let mut input = ~[];
  95. for _ in range(0, 2000) {
  96. input.push_all(r.choose(words.as_slice()));
  97. }
  98. debug!("de/inflate of {} bytes of random word-sequences",
  99. input.len());
  100. let cmp = deflate_bytes(input);
  101. let out = inflate_bytes(cmp.as_slice());
  102. debug!("{} bytes deflated to {} ({:.1f}% size)",
  103. input.len(), cmp.len(),
  104. 100.0 * ((cmp.len() as f64) / (input.len() as f64)));
  105. assert_eq!(input.as_slice(), out.as_slice());
  106. }
  107. }
  108. #[test]
  109. fn test_zlib_flate() {
  110. let bytes = vec!(1, 2, 3, 4, 5);
  111. let deflated = deflate_bytes(bytes.as_slice());
  112. let inflated = inflate_bytes(deflated.as_slice());
  113. assert_eq!(inflated.as_slice(), bytes.as_slice());
  114. }
  115. }