Skip to content

Commit 1b894c6

Browse files
committed
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`.
1 parent b4f5e78 commit 1b894c6

File tree

5 files changed

+52
-40
lines changed

5 files changed

+52
-40
lines changed

src/libflate/lib.rs

+44-24
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
2626
html_root_url = "http://doc.rust-lang.org/nightly/")]
2727

28-
#![feature(int_uint)]
2928
#![feature(libc)]
3029
#![feature(staged_api)]
3130
#![feature(unique)]
@@ -35,13 +34,33 @@
3534
extern crate libc;
3635

3736
use libc::{c_void, size_t, c_int};
37+
use std::fmt;
3838
use std::ops::Deref;
3939
use std::ptr::Unique;
4040
use std::slice;
4141

42+
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
43+
pub struct Error {
44+
_unused: (),
45+
}
46+
47+
impl Error {
48+
fn new() -> Error {
49+
Error {
50+
_unused: (),
51+
}
52+
}
53+
}
54+
55+
impl fmt::Debug for Error {
56+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57+
"decompression error".fmt(f)
58+
}
59+
}
60+
4261
pub struct Bytes {
4362
ptr: Unique<u8>,
44-
len: uint,
63+
len: usize,
4564
}
4665

4766
impl Deref for Bytes {
@@ -78,55 +97,56 @@ const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal"
7897
const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum
7998
const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum
8099

81-
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
100+
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes {
82101
unsafe {
83-
let mut outsz : size_t = 0;
102+
let mut outsz: size_t = 0;
84103
let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
85104
bytes.len() as size_t,
86105
&mut outsz,
87106
flags);
88-
if !res.is_null() {
89-
let res = Unique::new(res as *mut u8);
90-
Some(Bytes { ptr: res, len: outsz as uint })
91-
} else {
92-
None
107+
assert!(!res.is_null());
108+
Bytes {
109+
ptr: Unique::new(res as *mut u8),
110+
len: outsz as usize,
93111
}
94112
}
95113
}
96114

97115
/// Compress a buffer, without writing any sort of header on the output.
98-
pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
116+
pub fn deflate_bytes(bytes: &[u8]) -> Bytes {
99117
deflate_bytes_internal(bytes, LZ_NORM)
100118
}
101119

102120
/// Compress a buffer, using a header that zlib can understand.
103-
pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
121+
pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes {
104122
deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
105123
}
106124

107-
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
125+
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes,Error> {
108126
unsafe {
109-
let mut outsz : size_t = 0;
127+
let mut outsz: size_t = 0;
110128
let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
111129
bytes.len() as size_t,
112130
&mut outsz,
113131
flags);
114132
if !res.is_null() {
115-
let res = Unique::new(res as *mut u8);
116-
Some(Bytes { ptr: res, len: outsz as uint })
133+
Ok(Bytes {
134+
ptr: Unique::new(res as *mut u8),
135+
len: outsz as usize,
136+
})
117137
} else {
118-
None
138+
Err(Error::new())
119139
}
120140
}
121141
}
122142

123143
/// Decompress a buffer, without parsing any sort of header on the input.
124-
pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
144+
pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes,Error> {
125145
inflate_bytes_internal(bytes, 0)
126146
}
127147

128148
/// Decompress a buffer that starts with a zlib header.
129-
pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
149+
pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes,Error> {
130150
inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
131151
}
132152

@@ -140,7 +160,7 @@ mod tests {
140160
#[test]
141161
fn test_flate_round_trip() {
142162
let mut r = rand::thread_rng();
143-
let mut words = vec!();
163+
let mut words = vec![];
144164
for _ in 0..20 {
145165
let range = r.gen_range(1, 10);
146166
let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
@@ -153,8 +173,8 @@ mod tests {
153173
}
154174
debug!("de/inflate of {} bytes of random word-sequences",
155175
input.len());
156-
let cmp = deflate_bytes(&input).expect("deflation failed");
157-
let out = inflate_bytes(&cmp).expect("inflation failed");
176+
let cmp = deflate_bytes(&input);
177+
let out = inflate_bytes(&cmp).unwrap();
158178
debug!("{} bytes deflated to {} ({:.1}% size)",
159179
input.len(), cmp.len(),
160180
100.0 * ((cmp.len() as f64) / (input.len() as f64)));
@@ -164,9 +184,9 @@ mod tests {
164184

165185
#[test]
166186
fn test_zlib_flate() {
167-
let bytes = vec!(1, 2, 3, 4, 5);
168-
let deflated = deflate_bytes(&bytes).expect("deflation failed");
169-
let inflated = inflate_bytes(&deflated).expect("inflation failed");
187+
let bytes = vec![1, 2, 3, 4, 5];
188+
let deflated = deflate_bytes(&bytes);
189+
let inflated = inflate_bytes(&deflated).unwrap();
170190
assert_eq!(&*inflated, &*bytes);
171191
}
172192
}

src/librustc/metadata/loader.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -784,8 +784,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
784784
csz - vlen);
785785
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
786786
match flate::inflate_bytes(bytes) {
787-
Some(inflated) => return Ok(MetadataVec(inflated)),
788-
None => {}
787+
Ok(inflated) => return Ok(MetadataVec(inflated)),
788+
Err(_) => {}
789789
}
790790
}
791791
llvm::LLVMMoveToNextSection(si.llsi);

src/librustc_trans/back/link.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -626,12 +626,7 @@ fn link_rlib<'a>(sess: &'a Session,
626626
e))
627627
}
628628

629-
let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) {
630-
Some(compressed) => compressed,
631-
None => sess.fatal(&format!("failed to compress bytecode \
632-
from {}",
633-
bc_filename.display()))
634-
};
629+
let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
635630

636631
let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
637632
Ok(file) => file,

src/librustc_trans/back/lto.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
9696
(link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)];
9797

9898
match flate::inflate_bytes(compressed_data) {
99-
Some(inflated) => inflated,
100-
None => {
99+
Ok(inflated) => inflated,
100+
Err(_) => {
101101
sess.fatal(&format!("failed to decompress bc of `{}`",
102102
name))
103103
}
@@ -112,8 +112,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
112112
// the object must be in the old, pre-versioning format, so simply
113113
// inflate everything and let LLVM decide if it can make sense of it
114114
match flate::inflate_bytes(bc_encoded) {
115-
Some(bc) => bc,
116-
None => {
115+
Ok(bc) => bc,
116+
Err(_) => {
117117
sess.fatal(&format!("failed to decompress bc of `{}`",
118118
name))
119119
}

src/librustc_trans/trans/base.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2974,10 +2974,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
29742974
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
29752975
let metadata = encoder::encode_metadata(encode_parms, krate);
29762976
let mut compressed = encoder::metadata_encoding_version.to_vec();
2977-
compressed.push_all(&match flate::deflate_bytes(&metadata) {
2978-
Some(compressed) => compressed,
2979-
None => cx.sess().fatal("failed to compress metadata"),
2980-
});
2977+
compressed.push_all(&flate::deflate_bytes(&metadata));
29812978
let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
29822979
let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
29832980
let name = format!("rust_metadata_{}_{}",

0 commit comments

Comments
 (0)