#![allow(non_snake_case)] use std::os::raw::c_char; /// Matches `ZSTD_ErrorCode` / `ERR_enum` from the C API. #[repr(i32)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ZstdErrorCode { NoError = 0, Generic = 1, PrefixUnknown = 10, VersionUnsupported = 12, FrameParameterUnsupported = 14, FrameParameterWindowTooLarge = 16, CorruptionDetected = 20, ChecksumWrong = 22, LiteralsHeaderWrong = 24, DictionaryCorrupted = 30, DictionaryWrong = 32, DictionaryCreationFailed = 34, ParameterUnsupported = 40, ParameterCombinationUnsupported = 41, ParameterOutOfBound = 42, TableLogTooLarge = 44, MaxSymbolValueTooLarge = 46, MaxSymbolValueTooSmall = 48, CannotProduceUncompressedBlock = 49, StabilityConditionNotRespected = 50, StageWrong = 60, InitMissing = 62, MemoryAllocation = 64, WorkSpaceTooSmall = 66, DstSizeTooSmall = 70, SrcSizeWrong = 72, DstBufferNull = 74, NoForwardProgressDestFull = 80, NoForwardProgressInputEmpty = 82, FrameIndexTooLarge = 100, SeekableIO = 102, DstBufferWrong = 104, SrcBufferWrong = 105, SequenceProducerFailed = 106, ExternalSequencesInvalid = 107, MaxCode = 120, } /// Encode an error as a size_t-style error code: `(size_t)-(code)`. #[inline] pub fn ERROR(code: ZstdErrorCode) -> usize { (-(code as i32)) as usize } /// Returns true if `code` is an error (same as C `ERR_isError`). #[inline] pub fn ERR_isError(code: usize) -> bool { code > ERROR(ZstdErrorCode::MaxCode) } /// Extract the numeric `ZSTD_ErrorCode` from a size_t error value. /// /// C permits error-shaped values which aren't named enum variants, and /// `ERR_getErrorCode()` preserves those numeric values. Returning the ABI's /// integer representation avoids constructing an invalid Rust enum. #[inline] pub fn ERR_getErrorCode(code: usize) -> i32 { if !ERR_isError(code) { return ZstdErrorCode::NoError as i32; } 0usize.wrapping_sub(code) as i32 } #[inline] pub fn ERR_getErrorName(code: usize) -> *const c_char { ERR_getErrorString(ERR_getErrorCode(code)) } /// C ABI: `ERR_getErrorString` (error_private.c). #[no_mangle] pub extern "C" fn ERR_getErrorString(code: i32) -> *const c_char { match code { 0 => c"No error detected".as_ptr(), 1 => c"Error (generic)".as_ptr(), 10 => c"Unknown frame descriptor".as_ptr(), 12 => c"Version not supported".as_ptr(), 14 => c"Unsupported frame parameter".as_ptr(), 16 => c"Frame requires too much memory for decoding".as_ptr(), 20 => c"Data corruption detected".as_ptr(), 22 => c"Restored data doesn't match checksum".as_ptr(), 24 => c"Header of Literals' block doesn't respect format specification".as_ptr(), 30 => c"Dictionary is corrupted".as_ptr(), 32 => c"Dictionary mismatch".as_ptr(), 34 => c"Cannot create Dictionary from provided samples".as_ptr(), 40 => c"Unsupported parameter".as_ptr(), 41 => c"Unsupported combination of parameters".as_ptr(), 42 => c"Parameter is out of bound".as_ptr(), 44 => c"tableLog requires too much memory : unsupported".as_ptr(), 46 => c"Unsupported max Symbol Value : too large".as_ptr(), 48 => c"Specified maxSymbolValue is too small".as_ptr(), 49 => c"This mode cannot generate an uncompressed block".as_ptr(), 50 => c"pledged buffer stability condition is not respected".as_ptr(), 60 => c"Operation not authorized at current processing stage".as_ptr(), 62 => c"Context should be init first".as_ptr(), 64 => c"Allocation error : not enough memory".as_ptr(), 66 => c"workSpace buffer is not large enough".as_ptr(), 70 => c"Destination buffer is too small".as_ptr(), 72 => c"Src size is incorrect".as_ptr(), 74 => c"Operation on NULL destination buffer".as_ptr(), 80 => c"Operation made no progress over multiple calls, due to output buffer being full" .as_ptr(), 82 => c"Operation made no progress over multiple calls, due to input being empty".as_ptr(), 100 => c"Frame index is too large".as_ptr(), 102 => c"An I/O error occurred when reading/seeking".as_ptr(), 104 => c"Destination buffer is wrong".as_ptr(), 105 => c"Source buffer is wrong".as_ptr(), 106 => c"Block-level external sequence producer returned an error code".as_ptr(), 107 => c"External sequences are not valid".as_ptr(), _ => c"Unspecified error code".as_ptr(), } } /// C ABI: public `ZSTD_getErrorString` from zstd_errors.h. #[no_mangle] pub extern "C" fn ZSTD_getErrorString(code: i32) -> *const c_char { ERR_getErrorString(code) } #[cfg(test)] mod tests { use super::*; use std::ffi::CStr; #[test] fn size_t_error_encoding_matches_c() { let error = ERROR(ZstdErrorCode::DstSizeTooSmall); assert!(ERR_isError(error)); assert_eq!(ERR_getErrorCode(error), 70); assert!(!ERR_isError(0)); assert_eq!(ERR_getErrorCode(usize::MAX - 1), 2); assert_eq!(ERR_getErrorCode(ERROR(ZstdErrorCode::MaxCode)), 0); } #[test] fn error_names_match_the_public_api() { let name = unsafe { CStr::from_ptr(ERR_getErrorName(ERROR(ZstdErrorCode::ChecksumWrong))) }; assert_eq!(name.to_bytes(), b"Restored data doesn't match checksum"); let unknown = unsafe { CStr::from_ptr(ERR_getErrorString(2)) }; assert_eq!(unknown.to_bytes(), b"Unspecified error code"); } }