use std::any::Any;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Effect {
Allow,
Deny,
}
pub(crate) type Predicate<C> = dyn Fn(&C, &dyn Any) -> bool + Send + Sync;
pub(crate) struct Rule<A, S, C> {
pub(crate) effect: Effect,
pub(crate) action: A,
pub(crate) subject: S,
pub(crate) condition: Option<Box<Predicate<C>>>,
}
impl<A, S, C> Rule<A, S, C> {
pub(crate) fn unconditional(effect: Effect, action: A, subject: S) -> Self {
Self {
effect,
action,
subject,
condition: None,
}
}
pub(crate) fn conditional<R, F>(effect: Effect, action: A, subject: S, predicate: F) -> Self
where
R: 'static,
F: Fn(&C, &R) -> bool + Send + Sync + 'static,
{
let predicate: Box<Predicate<C>> =
Box::new(move |claims, resource| match resource.downcast_ref::<R>() {
Some(resource) => predicate(claims, resource),
None => false,
});
Self {
effect,
action,
subject,
condition: Some(predicate),
}
}
}