about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2015-03-15 21:35:48 +0100
committerTobias Bucher <tobiasbucher5991@gmail.com>2015-03-16 19:15:20 +0100
commit1b894c65de8e5bf03225afa29664045f5622e6d7 (patch)
treec0124f5885a5196d6c1d640e7b8c890abdb65132
parentb4f5e78b467fff62bcb5287f34940fd0037f2216 (diff)
Improve error handling in libflate
This removes the error case of the compression functions, the only errors that
can occur are incorrect parameters or an out-of-memory condition, both of which
are handled with panics in Rust.

Also introduces an extensible `Error` type instead of returning an `Option`.
-rw-r--r--src/libflate/lib.rs68
-rw-r--r--src/librustc/metadata/loader.rs4
-rw-r--r--src/librustc_trans/back/link.rs7
-rw-r--r--src/librustc_trans/back/lto.rs8
-rw-r--r--src/librustc_trans/trans/base.rs5
5 files changed, 52 insertions, 40 deletions
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index 100a9e36e86..695c71c73ed 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -25,7 +25,6 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
-#![feature(int_uint)]
 #![feature(libc)]
 #![feature(staged_api)]
 #![feature(unique)]
@@ -35,13 +34,33 @@
 extern crate libc;
 
 use libc::{c_void, size_t, c_int};
+use std::fmt;
 use std::ops::Deref;
 use std::ptr::Unique;
 use std::slice;
 
+#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct Error {
+    _unused: (),
+}
+
+impl Error {
+    fn new() -> Error {
+        Error {
+            _unused: (),
+        }
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "decompression error".fmt(f)
+    }
+}
+
 pub struct Bytes {
     ptr: Unique<u8>,
-    len: uint,
+    len: usize,
 }
 
 impl Deref for Bytes {
@@ -78,55 +97,56 @@ const LZ_NORM: c_int = 0x80;  // LZ with 128 probes, "normal"
 const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum
 const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum
 
-fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
+fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes {
     unsafe {
-        let mut outsz : size_t = 0;
+        let mut outsz: size_t = 0;
         let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
                                              bytes.len() as size_t,
                                              &mut outsz,
                                              flags);
-        if !res.is_null() {
-            let res = Unique::new(res as *mut u8);
-            Some(Bytes { ptr: res, len: outsz as uint })
-        } else {
-            None
+        assert!(!res.is_null());
+        Bytes {
+            ptr: Unique::new(res as *mut u8),
+            len: outsz as usize,
         }
     }
 }
 
 /// Compress a buffer, without writing any sort of header on the output.
-pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
+pub fn deflate_bytes(bytes: &[u8]) -> Bytes {
     deflate_bytes_internal(bytes, LZ_NORM)
 }
 
 /// Compress a buffer, using a header that zlib can understand.
-pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
+pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes {
     deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
 }
 
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes,Error> {
     unsafe {
-        let mut outsz : size_t = 0;
+        let mut outsz: size_t = 0;
         let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
                                                bytes.len() as size_t,
                                                &mut outsz,
                                                flags);
         if !res.is_null() {
-            let res = Unique::new(res as *mut u8);
-            Some(Bytes { ptr: res, len: outsz as uint })
+            Ok(Bytes {
+                ptr: Unique::new(res as *mut u8),
+                len: outsz as usize,
+            })
         } else {
-            None
+            Err(Error::new())
         }
     }
 }
 
 /// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
+pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes,Error> {
     inflate_bytes_internal(bytes, 0)
 }
 
 /// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes,Error> {
     inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
 }
 
@@ -140,7 +160,7 @@ mod tests {
     #[test]
     fn test_flate_round_trip() {
         let mut r = rand::thread_rng();
-        let mut words = vec!();
+        let mut words = vec![];
         for _ in 0..20 {
             let range = r.gen_range(1, 10);
             let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
@@ -153,8 +173,8 @@ mod tests {
             }
             debug!("de/inflate of {} bytes of random word-sequences",
                    input.len());
-            let cmp = deflate_bytes(&input).expect("deflation failed");
-            let out = inflate_bytes(&cmp).expect("inflation failed");
+            let cmp = deflate_bytes(&input);
+            let out = inflate_bytes(&cmp).unwrap();
             debug!("{} bytes deflated to {} ({:.1}% size)",
                    input.len(), cmp.len(),
                    100.0 * ((cmp.len() as f64) / (input.len() as f64)));
@@ -164,9 +184,9 @@ mod tests {
 
     #[test]
     fn test_zlib_flate() {
-        let bytes = vec!(1, 2, 3, 4, 5);
-        let deflated = deflate_bytes(&bytes).expect("deflation failed");
-        let inflated = inflate_bytes(&deflated).expect("inflation failed");
+        let bytes = vec![1, 2, 3, 4, 5];
+        let deflated = deflate_bytes(&bytes);
+        let inflated = inflate_bytes(&deflated).unwrap();
         assert_eq!(&*inflated, &*bytes);
     }
 }
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 8486bf782b0..e466dc8a3a0 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -784,8 +784,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
                        csz - vlen);
                 let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
                 match flate::inflate_bytes(bytes) {
-                    Some(inflated) => return Ok(MetadataVec(inflated)),
-                    None => {}
+                    Ok(inflated) => return Ok(MetadataVec(inflated)),
+                    Err(_) => {}
                 }
             }
             llvm::LLVMMoveToNextSection(si.llsi);
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 3087a8ea45d..34a23f3efac 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -626,12 +626,7 @@ fn link_rlib<'a>(sess: &'a Session,
                                                  e))
                 }
 
-                let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) {
-                    Some(compressed) => compressed,
-                    None => sess.fatal(&format!("failed to compress bytecode \
-                                                 from {}",
-                                                 bc_filename.display()))
-                };
+                let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
 
                 let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
                     Ok(file) => file,
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index db9966e0548..3893b974987 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -96,8 +96,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                             (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)];
 
                         match flate::inflate_bytes(compressed_data) {
-                            Some(inflated) => inflated,
-                            None => {
+                            Ok(inflated) => inflated,
+                            Err(_) => {
                                 sess.fatal(&format!("failed to decompress bc of `{}`",
                                                    name))
                             }
@@ -112,8 +112,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                 // the object must be in the old, pre-versioning format, so simply
                 // inflate everything and let LLVM decide if it can make sense of it
                     match flate::inflate_bytes(bc_encoded) {
-                        Some(bc) => bc,
-                        None => {
+                        Ok(bc) => bc,
+                        Err(_) => {
                             sess.fatal(&format!("failed to decompress bc of `{}`",
                                                name))
                         }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index ccf24f7e859..e9f58ec53df 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -2974,10 +2974,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
     let metadata = encoder::encode_metadata(encode_parms, krate);
     let mut compressed = encoder::metadata_encoding_version.to_vec();
-    compressed.push_all(&match flate::deflate_bytes(&metadata) {
-        Some(compressed) => compressed,
-        None => cx.sess().fatal("failed to compress metadata"),
-    });
+    compressed.push_all(&flate::deflate_bytes(&metadata));
     let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
     let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
     let name = format!("rust_metadata_{}_{}",