Skip to content

Commit

Permalink
struct bzFile: turn writing field into an enum
Browse files Browse the repository at this point in the history
  • Loading branch information
folkertdev committed Nov 6, 2024
1 parent bc8f998 commit 0e43d66
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 69 deletions.
105 changes: 77 additions & 28 deletions bzlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,11 @@ impl<T> DSlice<T> {
#[repr(C)]
pub struct bzFile {
pub handle: *mut FILE,
pub buf: [i8; 5000],
pub buf: [i8; BZ_MAX_UNUSED as usize],
pub bufN: i32,
pub strm: bz_stream,
pub lastErr: i32,
pub writing: bool,
pub operation: Operation,
pub initialisedOk: bool,
}

Expand Down Expand Up @@ -1818,7 +1818,7 @@ pub unsafe extern "C" fn BZ2_bzWriteOpen(
bzf.initialisedOk = false;
bzf.bufN = 0;
bzf.handle = f;
bzf.writing = true;
bzf.operation = Operation::Writing;
bzf.strm.bzalloc = None;
bzf.strm.bzfree = None;
bzf.strm.opaque = std::ptr::null_mut();
Expand Down Expand Up @@ -1864,7 +1864,7 @@ pub unsafe extern "C" fn BZ2_bzWrite(
return;
}

if !bzf.writing {
if !matches!(bzf.operation, Operation::Writing) {
BZ_SETERR!(bzerror, bzf, ReturnCode::BZ_SEQUENCE_ERROR);
return;
}
Expand Down Expand Up @@ -1948,7 +1948,7 @@ pub unsafe extern "C" fn BZ2_bzWriteClose64(
return;
};

if !bzf.writing {
if !matches!(bzf.operation, Operation::Writing) {
BZ_SETERR!(bzerror, bzf, ReturnCode::BZ_SEQUENCE_ERROR);
return;
}
Expand Down Expand Up @@ -2070,7 +2070,7 @@ pub unsafe extern "C" fn BZ2_bzReadOpen(
bzf.initialisedOk = false;
bzf.handle = f;
bzf.bufN = 0;
bzf.writing = false;
bzf.operation = Operation::Reading;
bzf.strm.bzalloc = None;
bzf.strm.bzfree = None;
bzf.strm.opaque = core::ptr::null_mut();
Expand Down Expand Up @@ -2111,7 +2111,7 @@ pub unsafe extern "C" fn BZ2_bzReadClose(bzerror: *mut libc::c_int, b: *mut libc
return;
};

if bzf.writing {
if !matches!(bzf.operation, Operation::Reading) {
BZ_SETERR!(bzerror, bzf, ReturnCode::BZ_SEQUENCE_ERROR);
return;
}
Expand Down Expand Up @@ -2144,7 +2144,7 @@ pub unsafe extern "C" fn BZ2_bzRead(
return 0;
}

if bzf.writing {
if !matches!(bzf.operation, Operation::Reading) {
BZ_SETERR!(bzerror, bzf, ReturnCode::BZ_SEQUENCE_ERROR);
return 0;
}
Expand Down Expand Up @@ -2327,6 +2327,13 @@ pub unsafe extern "C" fn BZ2_bzBuffToBuffDecompress(
}
}

#[derive(Copy, Clone)]
#[repr(u8)]
pub enum Operation {
Reading,
Writing,
}

enum OpenMode {
Pointer,
FileDescriptor(i32),
Expand All @@ -2337,11 +2344,6 @@ unsafe fn bzopen_or_bzdopen(
open_mode: OpenMode,
mode: *const libc::c_char,
) -> *mut libc::c_void {
enum Operation {
Reading,
Writing,
}

let mut bzerr = 0;
let mut unused: [libc::c_char; BZ_MAX_UNUSED as usize] = [0; BZ_MAX_UNUSED as usize];

Expand Down Expand Up @@ -2482,33 +2484,36 @@ pub unsafe extern "C" fn BZ2_bzflush(mut _b: *mut c_void) -> c_int {
pub unsafe extern "C" fn BZ2_bzclose(b: *mut libc::c_void) {
let mut bzerr: libc::c_int = 0;

let (fp, writing) = {
let (fp, operation) = {
let Some(bzf) = (b as *mut bzFile).as_mut() else {
return;
};

(bzf.handle, bzf.writing)
(bzf.handle, bzf.operation)
};

if writing {
BZ2_bzWriteClose(
&mut bzerr,
b,
false as i32,
core::ptr::null_mut(),
core::ptr::null_mut(),
);
if bzerr != 0 {
match operation {
Operation::Reading => {
BZ2_bzReadClose(&mut bzerr, b);
}
Operation::Writing => {
BZ2_bzWriteClose(
std::ptr::null_mut(),
&mut bzerr,
b,
true as i32,
false as i32,
core::ptr::null_mut(),
core::ptr::null_mut(),
);
if bzerr != 0 {
BZ2_bzWriteClose(
std::ptr::null_mut(),
b,
true as i32,
core::ptr::null_mut(),
core::ptr::null_mut(),
);
}
}
} else {
BZ2_bzReadClose(&mut bzerr, b);
}

if fp != stdin && fp != stdout {
Expand Down Expand Up @@ -2547,3 +2552,47 @@ pub unsafe extern "C" fn BZ2_bzerror(b: *const c_void, errnum: *mut c_int) -> *c
};
msg.as_ptr().cast::<c_char>()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn error_messages() {
let mut bz_file = bzFile {
handle: std::ptr::null_mut(),
buf: [0; 5000],
bufN: 0,
strm: bz_stream::zeroed(),
lastErr: 0,
operation: Operation::Reading,
initialisedOk: false,
};

for i in -17..1 {
bz_file.lastErr = i;

let mut errnum = 0;
let ptr = unsafe { BZ2_bzerror(&bz_file as *const _ as *const c_void, &mut errnum) };
assert!(!ptr.is_null());
let cstr = unsafe { CStr::from_ptr(ptr) };

match i {
1 => assert_eq!(cstr.to_str(), Ok("OK")),
0 => assert_eq!(cstr.to_str(), Ok("OK")),
-1 => assert_eq!(cstr.to_str(), Ok("SEQUENCE_ERROR")),
-2 => assert_eq!(cstr.to_str(), Ok("PARAM_ERROR")),
-3 => assert_eq!(cstr.to_str(), Ok("MEM_ERROR")),
-4 => assert_eq!(cstr.to_str(), Ok("DATA_ERROR")),
-5 => assert_eq!(cstr.to_str(), Ok("DATA_ERROR_MAGIC")),
-6 => assert_eq!(cstr.to_str(), Ok("IO_ERROR")),
-7 => assert_eq!(cstr.to_str(), Ok("UNEXPECTED_EOF")),
-8 => assert_eq!(cstr.to_str(), Ok("OUTBUFF_FULL")),
-9 => assert_eq!(cstr.to_str(), Ok("CONFIG_ERROR")),
_ => assert_eq!(cstr.to_str(), Ok("???")),
}

assert_eq!(i, errnum);
}
}
}
41 changes: 0 additions & 41 deletions test-libbzip2-rs-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,47 +639,6 @@ mod bzip2_testfiles {
#[test] fn dotnetzip_dancing_color() { assert_eq_decompress!("../../tests/input/bzip2-testfiles/dotnetzip/dancing-color.ps.bz2"); }
}

#[test]
fn error_messages() {
use libbzip2_rs_sys::bzlib::{bzFile, bz_stream, BZ2_bzerror};

let mut bz_file = bzFile {
handle: std::ptr::null_mut(),
buf: [0; 5000],
bufN: 0,
strm: bz_stream::zeroed(),
lastErr: 0,
writing: false,
initialisedOk: false,
};

for i in -17..1 {
bz_file.lastErr = i;

let mut errnum = 0;
let ptr = unsafe { BZ2_bzerror(&bz_file as *const _ as *const c_void, &mut errnum) };
assert!(!ptr.is_null());
let cstr = unsafe { CStr::from_ptr(ptr) };

match i {
1 => assert_eq!(cstr.to_str(), Ok("OK")),
0 => assert_eq!(cstr.to_str(), Ok("OK")),
-1 => assert_eq!(cstr.to_str(), Ok("SEQUENCE_ERROR")),
-2 => assert_eq!(cstr.to_str(), Ok("PARAM_ERROR")),
-3 => assert_eq!(cstr.to_str(), Ok("MEM_ERROR")),
-4 => assert_eq!(cstr.to_str(), Ok("DATA_ERROR")),
-5 => assert_eq!(cstr.to_str(), Ok("DATA_ERROR_MAGIC")),
-6 => assert_eq!(cstr.to_str(), Ok("IO_ERROR")),
-7 => assert_eq!(cstr.to_str(), Ok("UNEXPECTED_EOF")),
-8 => assert_eq!(cstr.to_str(), Ok("OUTBUFF_FULL")),
-9 => assert_eq!(cstr.to_str(), Ok("CONFIG_ERROR")),
_ => assert_eq!(cstr.to_str(), Ok("???")),
}

assert_eq!(i, errnum);
}
}

#[test]
fn decompress_init_edge_cases() {
use bzip2_sys::{BZ_MEM_ERROR, BZ_OK, BZ_PARAM_ERROR};
Expand Down

0 comments on commit 0e43d66

Please sign in to comment.