use crate::command::{ERR_NO_CONTEXT, ERR_PERM_PREFIX};
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum CoreError {
#[error("{0}")]
Permission(String),
#[error("{0}")]
NoContext(String),
#[error("{0}")]
Other(String),
}
impl CoreError {
pub fn code(&self) -> &'static str {
match self {
CoreError::Permission(_) => "permission",
CoreError::NoContext(_) => "no_context",
CoreError::Other(_) => "other",
}
}
pub fn classify(msg: String) -> Self {
if msg.starts_with(ERR_PERM_PREFIX) {
CoreError::Permission(msg)
} else if msg.starts_with(ERR_NO_CONTEXT) {
CoreError::NoContext(msg)
} else {
CoreError::Other(msg)
}
}
pub fn message(&self) -> &str {
match self {
CoreError::Permission(m) | CoreError::NoContext(m) | CoreError::Other(m) => m,
}
}
}
impl From<String> for CoreError {
fn from(msg: String) -> Self {
Self::classify(msg)
}
}
impl From<&str> for CoreError {
fn from(msg: &str) -> Self {
Self::classify(msg.to_string())
}
}
pub type CoreResult<T> = Result<T, CoreError>;
#[cfg(test)]
mod tests {
use super::CoreError;
use crate::command::{
ERR_NO_BATCH_WRITE, ERR_NO_CONTEXT, ERR_NO_DELETE, ERR_NO_WRITE, ERR_PERMISSION,
};
#[test]
fn classify_maps_sentinels_to_variants() {
for m in [
ERR_PERMISSION,
ERR_NO_WRITE,
ERR_NO_DELETE,
ERR_NO_BATCH_WRITE,
] {
let e = CoreError::classify(m.to_string());
assert_eq!(e, CoreError::Permission(m.to_string()));
assert_eq!(e.code(), "permission");
}
let e = CoreError::classify(ERR_NO_CONTEXT.to_string());
assert_eq!(e, CoreError::NoContext(ERR_NO_CONTEXT.to_string()));
assert_eq!(e.code(), "no_context");
let e = CoreError::classify("translate: 未知命令".to_string());
assert_eq!(e, CoreError::Other("translate: 未知命令".to_string()));
assert_eq!(e.code(), "other");
}
#[test]
fn display_preserves_message_verbatim() {
let e = CoreError::from(ERR_NO_WRITE);
assert_eq!(e.to_string(), ERR_NO_WRITE);
assert_eq!(e.message(), ERR_NO_WRITE);
}
#[test]
fn from_str_and_string_classify_identically() {
assert_eq!(
CoreError::from(ERR_PERMISSION),
CoreError::classify(ERR_PERMISSION.to_string())
);
}
}