From c5ce09bbd0bcf79258530af7e5c3d76d86a12b8a Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 3 Aug 2024 13:54:41 +0200 Subject: [PATCH] export `zError` --- libz-rs-sys/src/lib.rs | 8 +++++++ zlib-rs/src/deflate.rs | 27 ++++------------------- zlib-rs/src/lib.rs | 49 +++++++++++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/libz-rs-sys/src/lib.rs b/libz-rs-sys/src/lib.rs index ac1b0f66..39363eae 100644 --- a/libz-rs-sys/src/lib.rs +++ b/libz-rs-sys/src/lib.rs @@ -649,6 +649,14 @@ pub unsafe extern "C" fn deflateTune( } } +#[export_name = prefix!(zError)] +pub const unsafe extern "C" fn error_message(err: c_int) -> *const c_char { + match ReturnCode::try_from_c_int(err) { + Some(return_code) => return_code.error_message(), + None => core::ptr::null(), + } +} + // the first part of this version specifies the zlib that we're compatible with (in terms of // supported functions). In practice in most cases only the major version is checked, unless // specific functions that were added later are used. diff --git a/zlib-rs/src/deflate.rs b/zlib-rs/src/deflate.rs index e58dbb88..133d472b 100644 --- a/zlib-rs/src/deflate.rs +++ b/zlib-rs/src/deflate.rs @@ -1495,25 +1495,6 @@ enum Status { Finish = 3, } -const fn error_message(return_code: ReturnCode) -> *const core::ffi::c_char { - const TABLE: [&str; 10] = [ - "need dictionary\0", /* Z_NEED_DICT 2 */ - "stream end\0", /* Z_STREAM_END 1 */ - "\0", /* Z_OK 0 */ - "file error\0", /* Z_ERRNO (-1) */ - "stream error\0", /* Z_STREAM_ERROR (-2) */ - "data error\0", /* Z_DATA_ERROR (-3) */ - "insufficient memory\0", /* Z_MEM_ERROR (-4) */ - "buffer error\0", /* Z_BUF_ERROR (-5) */ - "incompatible version\0", /* Z_VERSION_ERROR (-6) */ - "\0", - ]; - - let index = (ReturnCode::NeedDict as i32 - return_code as i32) as usize; - - TABLE[index].as_ptr().cast() -} - const fn rank_flush(f: i32) -> i32 { // rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH ((f) * 2) - (if (f) > 4 { 9 } else { 0 }) @@ -2334,13 +2315,13 @@ pub fn deflate(stream: &mut DeflateStream, flush: DeflateFlush) -> ReturnCode { || (stream.state.status == Status::Finish && flush != DeflateFlush::Finish) { let err = ReturnCode::StreamError; - stream.msg = error_message(err); + stream.msg = err.error_message(); return err; } if stream.avail_out == 0 { let err = ReturnCode::BufError; - stream.msg = error_message(err); + stream.msg = err.error_message(); return err; } @@ -2370,14 +2351,14 @@ pub fn deflate(stream: &mut DeflateStream, flush: DeflateFlush) -> ReturnCode { && flush != DeflateFlush::Finish { let err = ReturnCode::BufError; - stream.msg = error_message(err); + stream.msg = err.error_message(); return err; } /* User must not provide more input after the first FINISH: */ if stream.state.status == Status::Finish && stream.avail_in != 0 { let err = ReturnCode::BufError; - stream.msg = error_message(err); + stream.msg = err.error_message(); return err; } diff --git a/zlib-rs/src/lib.rs b/zlib-rs/src/lib.rs index 92dbaf4c..6d377eab 100644 --- a/zlib-rs/src/lib.rs +++ b/zlib-rs/src/lib.rs @@ -175,19 +175,44 @@ pub enum ReturnCode { impl From for ReturnCode { fn from(value: i32) -> Self { - use ReturnCode::*; + match Self::try_from_c_int(value) { + Some(value) => value, + None => panic!("invalid return code {value}"), + } + } +} - match value { - 0 => Ok, - 1 => StreamEnd, - 2 => NeedDict, - -1 => ErrNo, - -2 => StreamError, - -3 => DataError, - -4 => MemError, - -5 => BufError, - -6 => VersionError, - _ => panic!("invalid return code {value}"), +impl ReturnCode { + const TABLE: [&'static str; 10] = [ + "need dictionary\0", /* Z_NEED_DICT 2 */ + "stream end\0", /* Z_STREAM_END 1 */ + "\0", /* Z_OK 0 */ + "file error\0", /* Z_ERRNO (-1) */ + "stream error\0", /* Z_STREAM_ERROR (-2) */ + "data error\0", /* Z_DATA_ERROR (-3) */ + "insufficient memory\0", /* Z_MEM_ERROR (-4) */ + "buffer error\0", /* Z_BUF_ERROR (-5) */ + "incompatible version\0", /* Z_VERSION_ERROR (-6) */ + "\0", + ]; + + pub const fn error_message(self) -> *const core::ffi::c_char { + let index = (ReturnCode::NeedDict as i32 - self as i32) as usize; + Self::TABLE[index].as_ptr().cast() + } + + pub const fn try_from_c_int(err: core::ffi::c_int) -> Option { + match err { + 0 => Some(Self::Ok), + 1 => Some(Self::StreamEnd), + 2 => Some(Self::NeedDict), + -1 => Some(Self::ErrNo), + -2 => Some(Self::StreamError), + -3 => Some(Self::DataError), + -4 => Some(Self::MemError), + -5 => Some(Self::BufError), + -6 => Some(Self::VersionError), + _ => None, } } }