use std::fmt;
const DER_SUCCESS: i32 = daos::daos_errno_DER_SUCCESS as i32;
const DER_NO_PERM: i32 = daos::daos_errno_DER_NO_PERM as i32;
const DER_NO_HDL: i32 = daos::daos_errno_DER_NO_HDL as i32;
const DER_INVAL: i32 = daos::daos_errno_DER_INVAL as i32;
const DER_NONEXIST: i32 = daos::daos_errno_DER_NONEXIST as i32;
const DER_UNREACH: i32 = daos::daos_errno_DER_UNREACH as i32;
const DER_NOSYS: i32 = daos::daos_errno_DER_NOSYS as i32;
const DER_TIMEDOUT: i32 = daos::daos_errno_DER_TIMEDOUT as i32;
const DER_BUSY: i32 = daos::daos_errno_DER_BUSY as i32;
const DER_TX_RESTART: i32 = daos::daos_errno_DER_TX_RESTART as i32;
pub type Result<T> = std::result::Result<T, DaosError>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DaosError {
InvalidArg,
NotFound,
Permission,
Timeout,
Busy,
Unreachable,
Unsupported,
TxRestart,
Unknown(i32),
Internal(String),
}
impl fmt::Display for DaosError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DaosError::InvalidArg => write!(f, "Invalid argument"),
DaosError::NotFound => write!(f, "Entity not found"),
DaosError::Permission => write!(f, "Permission denied"),
DaosError::Timeout => write!(f, "Operation timed out"),
DaosError::Busy => write!(f, "Resource is busy"),
DaosError::Unreachable => write!(f, "Target is unreachable"),
DaosError::Unsupported => write!(f, "Operation not supported"),
DaosError::TxRestart => write!(f, "Transaction must be restarted"),
DaosError::Unknown(code) => write!(f, "Unknown error: {}", code),
DaosError::Internal(msg) => write!(f, "Internal error: {}", msg),
}
}
}
impl std::error::Error for DaosError {}
pub type RawDaosResult = i32;
#[inline]
pub fn from_daos_errno(code: i32) -> DaosError {
if code == DER_SUCCESS {
return DaosError::Internal("unexpected success code".to_string());
}
let normalized = if code < 0 { -code } else { code };
match normalized {
DER_NO_PERM => DaosError::Permission,
DER_NO_HDL | DER_INVAL => DaosError::InvalidArg,
DER_NONEXIST => DaosError::NotFound,
DER_UNREACH => DaosError::Unreachable,
DER_NOSYS => DaosError::Unsupported,
DER_TIMEDOUT => DaosError::Timeout,
DER_BUSY => DaosError::Busy,
DER_TX_RESTART => DaosError::TxRestart,
_ => DaosError::Unknown(code),
}
}
impl From<i32> for DaosError {
fn from(code: i32) -> Self {
from_daos_errno(code)
}
}
impl DaosError {
#[inline]
pub const fn code(&self) -> Option<i32> {
match self {
DaosError::Unknown(code) => Some(*code),
_ => None,
}
}
}
pub trait ContextExt<T> {
fn context(self, msg: impl Into<String>) -> Result<T>;
}
impl<T> ContextExt<T> for Result<T> {
fn context(self, msg: impl Into<String>) -> Result<T> {
self.map_err(|e| {
if let Some(code) = e.code() {
DaosError::Unknown(code)
} else {
DaosError::Internal(msg.into())
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_known_error_mappings() {
assert!(matches!(from_daos_errno(1001), DaosError::Permission)); assert!(matches!(from_daos_errno(1002), DaosError::InvalidArg)); assert!(matches!(from_daos_errno(1003), DaosError::InvalidArg)); assert!(matches!(from_daos_errno(1005), DaosError::NotFound)); assert!(matches!(from_daos_errno(1006), DaosError::Unreachable)); assert!(matches!(from_daos_errno(1010), DaosError::Unsupported)); assert!(matches!(from_daos_errno(1011), DaosError::Timeout)); assert!(matches!(from_daos_errno(1012), DaosError::Busy)); assert!(matches!(from_daos_errno(2025), DaosError::TxRestart)); }
#[test]
fn test_negative_error_mappings() {
assert!(matches!(from_daos_errno(-1001), DaosError::Permission));
assert!(matches!(from_daos_errno(-1003), DaosError::InvalidArg));
assert!(matches!(from_daos_errno(-1005), DaosError::NotFound));
assert!(matches!(from_daos_errno(-2025), DaosError::TxRestart));
}
#[test]
fn test_unknown_error_preserved() {
let err = from_daos_errno(9999);
assert!(matches!(err, DaosError::Unknown(9999)));
let err = from_daos_errno(-1);
assert!(matches!(err, DaosError::Unknown(-1)));
}
#[test]
fn test_error_display() {
assert_eq!(format!("{}", DaosError::InvalidArg), "Invalid argument");
assert_eq!(format!("{}", DaosError::NotFound), "Entity not found");
assert_eq!(
format!("{}", DaosError::Unknown(1234)),
"Unknown error: 1234"
);
}
#[test]
fn test_error_code_extraction() {
let err = DaosError::Unknown(5001);
assert_eq!(err.code(), Some(5001));
let err = DaosError::InvalidArg;
assert_eq!(err.code(), None);
}
#[test]
fn test_from_i32() {
let err: DaosError = 1003i32.into();
assert!(matches!(err, DaosError::InvalidArg));
}
}