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