casbin/
convert.rs

1#![allow(non_snake_case)]
2use crate::{Adapter, DefaultModel, Model, NullAdapter, Result};
3
4#[cfg(not(target_arch = "wasm32"))]
5use crate::FileAdapter;
6
7use async_trait::async_trait;
8use rhai::{serde::to_dynamic, Dynamic};
9use serde::Serialize;
10
11use std::{
12    collections::hash_map::DefaultHasher,
13    hash::{Hash, Hasher},
14};
15
16#[async_trait]
17pub trait TryIntoModel: Send + Sync {
18    async fn try_into_model(self) -> Result<Box<dyn Model>>;
19}
20
21#[async_trait]
22pub trait TryIntoAdapter: Send + Sync {
23    async fn try_into_adapter(self) -> Result<Box<dyn Adapter>>;
24}
25
26#[async_trait]
27impl TryIntoModel for &'static str {
28    async fn try_into_model(self) -> Result<Box<dyn Model>> {
29        #[cfg(not(target_arch = "wasm32"))]
30        {
31            Ok(Box::new(DefaultModel::from_file(self).await?))
32        }
33        #[cfg(target_arch = "wasm32")]
34        {
35            Ok(Box::new(DefaultModel::from_str(self).await?))
36        }
37    }
38}
39
40#[async_trait]
41impl<T> TryIntoModel for Option<T>
42where
43    T: TryIntoModel,
44{
45    #[allow(clippy::box_default)]
46    async fn try_into_model(self) -> Result<Box<dyn Model>> {
47        if let Some(m) = self {
48            m.try_into_model().await
49        } else {
50            Ok(Box::new(DefaultModel::default()))
51        }
52    }
53}
54
55#[async_trait]
56impl TryIntoAdapter for &'static str {
57    async fn try_into_adapter(self) -> Result<Box<dyn Adapter>> {
58        #[cfg(not(target_arch = "wasm32"))]
59        {
60            Ok(Box::new(FileAdapter::new(self)))
61        }
62
63        #[cfg(target_arch = "wasm32")]
64        {
65            Ok(Box::new(NullAdapter))
66        }
67    }
68}
69
70#[async_trait]
71impl<T> TryIntoAdapter for Option<T>
72where
73    T: TryIntoAdapter,
74{
75    async fn try_into_adapter(self) -> Result<Box<dyn Adapter>> {
76        if let Some(a) = self {
77            a.try_into_adapter().await
78        } else {
79            Ok(Box::new(NullAdapter))
80        }
81    }
82}
83
84#[allow(clippy::unit_arg)]
85#[async_trait]
86impl TryIntoAdapter for () {
87    async fn try_into_adapter(self) -> Result<Box<dyn Adapter>> {
88        Ok(Box::new(NullAdapter))
89    }
90}
91
92#[async_trait]
93impl<T> TryIntoModel for T
94where
95    T: Model + 'static,
96{
97    async fn try_into_model(self) -> Result<Box<dyn Model>> {
98        Ok(Box::new(self))
99    }
100}
101
102#[async_trait]
103impl<T> TryIntoAdapter for T
104where
105    T: Adapter + 'static,
106{
107    async fn try_into_adapter(self) -> Result<Box<dyn Adapter>> {
108        Ok(Box::new(self))
109    }
110}
111
112pub trait EnforceArgs {
113    fn try_into_vec(self) -> Result<Vec<Dynamic>>;
114    fn cache_key(&self) -> u64;
115}
116
117impl<T> EnforceArgs for Vec<T>
118where
119    T: Into<Dynamic> + Hash + Clone,
120{
121    fn try_into_vec(self) -> Result<Vec<Dynamic>> {
122        Ok(self.into_iter().map(|x| x.into()).collect())
123    }
124
125    fn cache_key(&self) -> u64 {
126        let mut hasher = DefaultHasher::new();
127        self.hash(&mut hasher);
128        hasher.finish()
129    }
130}
131
132macro_rules! impl_args {
133    ($($p:ident),*) => {
134        impl<$($p: Serialize + Hash),*> EnforceArgs for ($($p,)*)
135        {
136            fn try_into_vec(self) -> Result<Vec<Dynamic>> {
137                let ($($p,)*) = self;
138                let _v = vec![$(to_dynamic($p)?,)*];
139
140                Ok(_v)
141            }
142
143            fn cache_key(&self) -> u64 {
144                let ($($p,)*) = self;
145                let mut _hasher = DefaultHasher::new();
146
147                $($p.hash(&mut _hasher);)*
148
149                _hasher.finish()
150            }
151        }
152
153        impl_args!(@pop $($p),*);
154    };
155    (@pop) => {
156    };
157    (@pop $head:ident) => {
158        impl_args!();
159    };
160    (@pop $head:ident $(, $tail:ident)+) => {
161        impl_args!($($tail),*);
162    };
163}
164
165impl_args!(A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V);