pub type FrozenResult<T> = Result<T, FrozenError>;
#[derive(Clone)]
pub struct FrozenError {
pub module: u8,
pub domain: u8,
pub reason: u8,
pub context: String,
}
impl FrozenError {
#[inline(always)]
pub fn new(module: u8, domain: u8, code: ErrCode, errmsg: &str) -> Self {
Self { module, domain, reason: code.reason, context: format!("[{}] {}", code.detail, errmsg) }
}
#[inline(always)]
pub fn new_raw<E: std::fmt::Display>(module: u8, domain: u8, code: ErrCode, err: E) -> Self {
Self { domain, module, reason: code.reason, context: format!("[{}] {}", code.detail, err) }
}
#[inline(always)]
pub fn is_equal(&self, err: &FrozenError) -> bool {
self == err
}
}
impl std::fmt::Debug for FrozenError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FrozenError")
.field("Module", &self.module)
.field("Domain", &self.domain)
.field("Reason", &self.reason)
.finish()
}
}
impl PartialEq for FrozenError {
fn eq(&self, other: &Self) -> bool {
(self.module == other.module) && (self.domain == other.domain) && (self.reason == other.reason)
}
}
#[derive(Debug, Clone)]
pub struct ErrCode {
pub reason: u8,
pub detail: &'static str,
}
impl ErrCode {
#[inline]
pub const fn new(reason: u8, detail: &'static str) -> Self {
Self { reason, detail }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ok_context_exact_format() {
let err = FrozenError::new(1, 2, ErrCode::new(3, "io"), "failure");
assert_eq!(err.context, "[io] failure");
}
#[test]
fn ok_empty_message() {
let err = FrozenError::new(1, 2, ErrCode::new(3, "io"), "");
assert_eq!(err.context, "[io] ");
}
#[test]
fn ok_empty_detail() {
let err = FrozenError::new(1, 2, ErrCode::new(3, ""), "failure");
assert_eq!(err.context, "[] failure");
}
#[test]
fn ok_new_and_new_raw_same_id() {
let e1 = FrozenError::new(1, 2, ErrCode::new(3, "io"), "fail");
let io_err = std::io::Error::new(std::io::ErrorKind::Other, "fail");
let e2 = FrozenError::new_raw(1, 2, ErrCode::new(3, "io"), io_err);
assert_eq!(e1, e2);
}
#[test]
fn ok_context_formatting() {
let err = FrozenError::new(1, 1, ErrCode::new(1, "io"), "disk failure");
assert_eq!(err.context, "[io] disk failure");
}
#[test]
fn ok_new_raw_uses_display() {
let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let err = FrozenError::new_raw(1, 2, ErrCode::new(3, "io"), io_err);
assert!(err.context.contains("[io]"));
assert!(err.context.contains("access denied"));
}
#[test]
fn ok_compare_same_id_different_context() {
let e1 = FrozenError::new(1, 2, ErrCode::new(3, "io"), "a");
let e2 = FrozenError::new(1, 2, ErrCode::new(3, "io"), "b");
assert_eq!(e1, e2);
}
#[test]
fn ok_compare_different_id() {
let e1 = FrozenError::new(1, 2, ErrCode::new(3, "io"), "a");
let e2 = FrozenError::new(1, 2, ErrCode::new(4, "io"), "a");
assert_ne!(e1, e2);
}
}