use crate::error::AspectError;
use crate::joinpoint::{JoinPoint, ProceedingJoinPoint};
use std::any::Any;
pub trait Aspect: Send + Sync {
fn before(&self, _ctx: &JoinPoint) {}
fn after(&self, _ctx: &JoinPoint, _result: &dyn Any) {}
fn after_error(&self, _ctx: &JoinPoint, _error: &AspectError) {}
fn around(&self, pjp: ProceedingJoinPoint) -> Result<Box<dyn Any>, AspectError> {
let ctx = pjp.context().clone();
self.before(&ctx);
let result = pjp.proceed();
match &result {
Ok(value) => {
self.after(&ctx, value.as_ref());
}
Err(error) => {
self.after_error(&ctx, error);
}
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Default)]
struct CountingAspect {
before_count: std::sync::Arc<std::sync::atomic::AtomicUsize>,
after_count: std::sync::Arc<std::sync::atomic::AtomicUsize>,
}
impl Aspect for CountingAspect {
fn before(&self, _ctx: &JoinPoint) {
self.before_count
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
fn after(&self, _ctx: &JoinPoint, _result: &dyn Any) {
self.after_count
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
}
#[test]
fn test_aspect_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<CountingAspect>();
assert_sync::<CountingAspect>();
}
}