use thiserror::Error;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Error)]
pub(crate) enum CoreError {
#[error("internal encoder failure")]
Generic,
#[error("entropy table log too large")]
TableLogTooLarge,
#[error("symbol value too large for the table")]
MaxSymbolValueTooLarge,
#[error("symbol value above the declared maximum")]
MaxSymbolValueTooSmall,
#[error("destination buffer too small")]
DstSizeTooSmall,
#[error("source size does not match the declared size")]
SrcSizeWrong,
#[error("operation not allowed at this stage")]
StageWrong,
}
impl CoreError {
pub(crate) const fn error_code(self) -> usize {
match self {
Self::Generic => 1,
Self::TableLogTooLarge => 44,
Self::MaxSymbolValueTooLarge => 46,
Self::MaxSymbolValueTooSmall => 48,
Self::DstSizeTooSmall => 70,
Self::SrcSizeWrong => 72,
Self::StageWrong => 60,
}
}
pub(crate) const fn code(self) -> usize {
0usize.wrapping_sub(self.error_code())
}
}
pub(crate) const fn is_error_code(value: usize) -> bool {
value > 0usize.wrapping_sub(120)
}
pub(crate) const fn as_code(result: Result<usize, CoreError>) -> usize {
match result {
Ok(value) => value,
Err(error) => error.code(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn codes_are_negated_reference_values() {
assert_eq!(CoreError::Generic.code(), usize::MAX);
assert_eq!(CoreError::DstSizeTooSmall.code(), usize::MAX - 69);
for error in [
CoreError::Generic,
CoreError::TableLogTooLarge,
CoreError::MaxSymbolValueTooLarge,
CoreError::MaxSymbolValueTooSmall,
CoreError::DstSizeTooSmall,
CoreError::SrcSizeWrong,
CoreError::StageWrong,
] {
assert!(is_error_code(error.code()), "{error}");
assert_eq!(as_code(Err(error)), error.code());
}
assert!(!is_error_code(1 << 40));
assert_eq!(as_code(Ok(5)), 5);
}
}