use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ApiError {
Unavailable { reason: String },
NotFound { what: String },
Refused { reason: String },
}
impl ApiError {
pub fn is_transient(&self) -> bool {
matches!(self, Self::Unavailable { .. })
}
}
impl fmt::Display for ApiError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unavailable { reason } => write!(f, "the memory kernel is unavailable: {reason}"),
Self::NotFound { what } => write!(f, "not found: {what}"),
Self::Refused { reason } => write!(f, "the memory kernel refused: {reason}"),
}
}
}
impl std::error::Error for ApiError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn only_unavailability_invites_a_retry() {
assert!(
ApiError::Unavailable {
reason: "opening".to_string()
}
.is_transient()
);
assert!(
!ApiError::NotFound {
what: "about project:x".to_string()
}
.is_transient()
);
assert!(
!ApiError::Refused {
reason: "empty about".to_string()
}
.is_transient(),
"retrying a refusal unchanged asks the same question and earns the same answer"
);
}
}