use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum AspectError {
ExecutionError {
message: String,
source: Option<Box<dyn Error + Send + Sync>>,
},
WeavingError {
message: String,
},
Custom(Box<dyn Error + Send + Sync>),
}
impl AspectError {
pub fn execution(message: impl Into<String>) -> Self {
Self::ExecutionError {
message: message.into(),
source: None,
}
}
pub fn execution_with_source(
message: impl Into<String>,
source: impl Error + Send + Sync + 'static,
) -> Self {
Self::ExecutionError {
message: message.into(),
source: Some(Box::new(source)),
}
}
pub fn weaving(message: impl Into<String>) -> Self {
Self::WeavingError {
message: message.into(),
}
}
pub fn custom(error: impl Error + Send + Sync + 'static) -> Self {
Self::Custom(Box::new(error))
}
}
impl fmt::Display for AspectError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ExecutionError { message, .. } => {
write!(f, "Execution error: {}", message)
}
Self::WeavingError { message } => {
write!(f, "Weaving error: {}", message)
}
Self::Custom(err) => write!(f, "Custom error: {}", err),
}
}
}
impl Error for AspectError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::ExecutionError { source, .. } => {
source.as_ref().map(|e| e.as_ref() as &(dyn Error + 'static))
}
Self::Custom(err) => Some(err.as_ref()),
_ => None,
}
}
}
impl From<String> for AspectError {
fn from(s: String) -> Self {
Self::execution(s)
}
}
impl From<&str> for AspectError {
fn from(s: &str) -> Self {
Self::execution(s)
}
}
impl From<Box<dyn Error + Send + Sync>> for AspectError {
fn from(err: Box<dyn Error + Send + Sync>) -> Self {
Self::Custom(err)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io;
#[test]
fn test_execution_error() {
let err = AspectError::execution("test error");
assert!(matches!(err, AspectError::ExecutionError { .. }));
assert_eq!(err.to_string(), "Execution error: test error");
}
#[test]
fn test_execution_error_with_source() {
let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
let err = AspectError::execution_with_source("read failed", io_err);
assert!(err.source().is_some());
}
#[test]
fn test_weaving_error() {
let err = AspectError::weaving("invalid pointcut");
assert!(matches!(err, AspectError::WeavingError { .. }));
assert_eq!(err.to_string(), "Weaving error: invalid pointcut");
}
#[test]
fn test_custom_error() {
let io_err = io::Error::new(io::ErrorKind::Other, "custom");
let err = AspectError::custom(io_err);
assert!(matches!(err, AspectError::Custom(_)));
}
#[test]
fn test_from_string() {
let err: AspectError = "error message".into();
assert!(matches!(err, AspectError::ExecutionError { .. }));
}
}