use std::fmt;
use std::sync::Arc;
use ferrin_spec::BoxFuture;
use ferrin_spec::JsonValue;
use crate::error::PolicyError;
pub trait PolicyClient: Send + Sync + 'static {
fn evaluate<'a>(
&'a self,
path: &'a str,
input: JsonValue,
) -> BoxFuture<'a, Result<JsonValue, PolicyError>>;
}
impl<T: PolicyClient + ?Sized> PolicyClient for Arc<T> {
fn evaluate<'a>(
&'a self,
path: &'a str,
input: JsonValue,
) -> BoxFuture<'a, Result<JsonValue, PolicyError>> {
(**self).evaluate(path, input)
}
}
pub type SharedPolicyClient = Arc<dyn PolicyClient>;
pub struct PolicyClientFn<F>(F);
pub fn policy_client<F>(f: F) -> PolicyClientFn<F>
where
F: Fn(&str, JsonValue) -> Result<JsonValue, PolicyError> + Send + Sync + 'static,
{
PolicyClientFn(f)
}
impl<F> fmt::Debug for PolicyClientFn<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("PolicyClientFn(..)")
}
}
impl<F> PolicyClient for PolicyClientFn<F>
where
F: Fn(&str, JsonValue) -> Result<JsonValue, PolicyError> + Send + Sync + 'static,
{
fn evaluate<'a>(
&'a self,
path: &'a str,
input: JsonValue,
) -> BoxFuture<'a, Result<JsonValue, PolicyError>> {
let result = (self.0)(path, input);
Box::pin(async move { result })
}
}