1use std::fmt;
4use std::sync::Arc;
5
6use ferrin_spec::BoxFuture;
7use ferrin_spec::JsonValue;
8
9use crate::error::PolicyError;
10
11pub trait PolicyClient: Send + Sync + 'static {
20 fn evaluate<'a>(
22 &'a self,
23 path: &'a str,
24 input: JsonValue,
25 ) -> BoxFuture<'a, Result<JsonValue, PolicyError>>;
26}
27
28impl<T: PolicyClient + ?Sized> PolicyClient for Arc<T> {
29 fn evaluate<'a>(
30 &'a self,
31 path: &'a str,
32 input: JsonValue,
33 ) -> BoxFuture<'a, Result<JsonValue, PolicyError>> {
34 (**self).evaluate(path, input)
35 }
36}
37
38pub type SharedPolicyClient = Arc<dyn PolicyClient>;
40
41pub struct PolicyClientFn<F>(F);
43
44pub fn policy_client<F>(f: F) -> PolicyClientFn<F>
47where
48 F: Fn(&str, JsonValue) -> Result<JsonValue, PolicyError> + Send + Sync + 'static,
49{
50 PolicyClientFn(f)
51}
52
53impl<F> fmt::Debug for PolicyClientFn<F> {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 f.write_str("PolicyClientFn(..)")
56 }
57}
58
59impl<F> PolicyClient for PolicyClientFn<F>
60where
61 F: Fn(&str, JsonValue) -> Result<JsonValue, PolicyError> + Send + Sync + 'static,
62{
63 fn evaluate<'a>(
64 &'a self,
65 path: &'a str,
66 input: JsonValue,
67 ) -> BoxFuture<'a, Result<JsonValue, PolicyError>> {
68 let result = (self.0)(path, input);
69 Box::pin(async move { result })
70 }
71}