提交 1b894c65 编写于 作者: T Tobias Bucher

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`.
上级 b4f5e78b
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")] html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(int_uint)]
#![feature(libc)] #![feature(libc)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(unique)] #![feature(unique)]
...@@ -35,13 +34,33 @@ ...@@ -35,13 +34,33 @@
extern crate libc; extern crate libc;
use libc::{c_void, size_t, c_int}; use libc::{c_void, size_t, c_int};
use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::ptr::Unique; use std::ptr::Unique;
use std::slice; 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 { pub struct Bytes {
ptr: Unique<u8>, ptr: Unique<u8>,
len: uint, len: usize,
} }
impl Deref for Bytes { impl Deref for Bytes {
...@@ -78,55 +97,56 @@ fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void, ...@@ -78,55 +97,56 @@ fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum 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 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 { 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 _, let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
bytes.len() as size_t, bytes.len() as size_t,
&mut outsz, &mut outsz,
flags); flags);
if !res.is_null() { assert!(!res.is_null());
let res = Unique::new(res as *mut u8); Bytes {
Some(Bytes { ptr: res, len: outsz as uint }) ptr: Unique::new(res as *mut u8),
} else { len: outsz as usize,
None
} }
} }
} }
/// Compress a buffer, without writing any sort of header on the output. /// 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) deflate_bytes_internal(bytes, LZ_NORM)
} }
/// Compress a buffer, using a header that zlib can understand. /// 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) 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 { 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 _, let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
bytes.len() as size_t, bytes.len() as size_t,
&mut outsz, &mut outsz,
flags); flags);
if !res.is_null() { if !res.is_null() {
let res = Unique::new(res as *mut u8); Ok(Bytes {
Some(Bytes { ptr: res, len: outsz as uint }) ptr: Unique::new(res as *mut u8),
len: outsz as usize,
})
} else { } else {
None Err(Error::new())
} }
} }
} }
/// Decompress a buffer, without parsing any sort of header on the input. /// 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) inflate_bytes_internal(bytes, 0)
} }
/// Decompress a buffer that starts with a zlib header. /// 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) inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
} }
...@@ -140,7 +160,7 @@ mod tests { ...@@ -140,7 +160,7 @@ mod tests {
#[test] #[test]
fn test_flate_round_trip() { fn test_flate_round_trip() {
let mut r = rand::thread_rng(); let mut r = rand::thread_rng();
let mut words = vec!(); let mut words = vec![];
for _ in 0..20 { for _ in 0..20 {
let range = r.gen_range(1, 10); let range = r.gen_range(1, 10);
let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>(); let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
...@@ -153,8 +173,8 @@ fn test_flate_round_trip() { ...@@ -153,8 +173,8 @@ fn test_flate_round_trip() {
} }
debug!("de/inflate of {} bytes of random word-sequences", debug!("de/inflate of {} bytes of random word-sequences",
input.len()); input.len());
let cmp = deflate_bytes(&input).expect("deflation failed"); let cmp = deflate_bytes(&input);
let out = inflate_bytes(&cmp).expect("inflation failed"); let out = inflate_bytes(&cmp).unwrap();
debug!("{} bytes deflated to {} ({:.1}% size)", debug!("{} bytes deflated to {} ({:.1}% size)",
input.len(), cmp.len(), input.len(), cmp.len(),
100.0 * ((cmp.len() as f64) / (input.len() as f64))); 100.0 * ((cmp.len() as f64) / (input.len() as f64)));
...@@ -164,9 +184,9 @@ fn test_flate_round_trip() { ...@@ -164,9 +184,9 @@ fn test_flate_round_trip() {
#[test] #[test]
fn test_zlib_flate() { fn test_zlib_flate() {
let bytes = vec!(1, 2, 3, 4, 5); let bytes = vec![1, 2, 3, 4, 5];
let deflated = deflate_bytes(&bytes).expect("deflation failed"); let deflated = deflate_bytes(&bytes);
let inflated = inflate_bytes(&deflated).expect("inflation failed"); let inflated = inflate_bytes(&deflated).unwrap();
assert_eq!(&*inflated, &*bytes); assert_eq!(&*inflated, &*bytes);
} }
} }
...@@ -784,8 +784,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo ...@@ -784,8 +784,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
csz - vlen); csz - vlen);
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen); let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
match flate::inflate_bytes(bytes) { match flate::inflate_bytes(bytes) {
Some(inflated) => return Ok(MetadataVec(inflated)), Ok(inflated) => return Ok(MetadataVec(inflated)),
None => {} Err(_) => {}
} }
} }
llvm::LLVMMoveToNextSection(si.llsi); llvm::LLVMMoveToNextSection(si.llsi);
......
...@@ -626,12 +626,7 @@ fn link_rlib<'a>(sess: &'a Session, ...@@ -626,12 +626,7 @@ fn link_rlib<'a>(sess: &'a Session,
e)) e))
} }
let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) { let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
Some(compressed) => compressed,
None => sess.fatal(&format!("failed to compress bytecode \
from {}",
bc_filename.display()))
};
let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
Ok(file) => file, Ok(file) => file,
......
...@@ -96,8 +96,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, ...@@ -96,8 +96,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
(link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)]; (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)];
match flate::inflate_bytes(compressed_data) { match flate::inflate_bytes(compressed_data) {
Some(inflated) => inflated, Ok(inflated) => inflated,
None => { Err(_) => {
sess.fatal(&format!("failed to decompress bc of `{}`", sess.fatal(&format!("failed to decompress bc of `{}`",
name)) name))
} }
...@@ -112,8 +112,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, ...@@ -112,8 +112,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
// the object must be in the old, pre-versioning format, so simply // 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 // inflate everything and let LLVM decide if it can make sense of it
match flate::inflate_bytes(bc_encoded) { match flate::inflate_bytes(bc_encoded) {
Some(bc) => bc, Ok(bc) => bc,
None => { Err(_) => {
sess.fatal(&format!("failed to decompress bc of `{}`", sess.fatal(&format!("failed to decompress bc of `{}`",
name)) name))
} }
......
...@@ -2974,10 +2974,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> { ...@@ -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 encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
let metadata = encoder::encode_metadata(encode_parms, krate); let metadata = encoder::encode_metadata(encode_parms, krate);
let mut compressed = encoder::metadata_encoding_version.to_vec(); let mut compressed = encoder::metadata_encoding_version.to_vec();
compressed.push_all(&match flate::deflate_bytes(&metadata) { compressed.push_all(&flate::deflate_bytes(&metadata));
Some(compressed) => compressed,
None => cx.sess().fatal("failed to compress metadata"),
});
let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]); let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
let name = format!("rust_metadata_{}_{}", let name = format!("rust_metadata_{}_{}",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册