1#[macro_use]
2mod macros;
3mod sanitize;
4mod validate;
5mod view;
6mod visitable;
7
8pub use sanitize::*;
9pub use validate::*;
10pub use view::*;
11pub use visitable::*;
12
13pub use canic_cdk::structures::storable::Storable;
16pub use num_traits::{FromPrimitive as NumFromPrimitive, NumCast, ToPrimitive as NumToPrimitive};
17pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
18pub use std::{
19 cmp::{Eq, Ordering, PartialEq},
20 convert::{AsRef, From, Into},
21 default::Default,
22 fmt::{Debug, Display},
23 hash::Hash,
24 iter::IntoIterator,
25 ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign},
26 str::FromStr,
27};
28
29use crate::{
30 IndexSpec, Key, Value,
31 db::primitives::{
32 BoolEqualityFilterKind, BoolListFilterKind, FilterKind, Int64RangeFilterKind,
33 IntListFilterKind, Nat64RangeFilterKind, NatListFilterKind, TextFilterKind,
34 TextListFilterKind,
35 },
36};
37
38pub trait Kind: Path + 'static {}
48
49impl<T> Kind for T where T: Path + 'static {}
50
51pub trait CanisterKind: Kind {}
56
57pub trait EntityKind: Kind + TypeKind + FieldValues {
62 type PrimaryKey: Copy + Into<Key>;
63 type Store: StoreKind;
64 type Canister: CanisterKind; const ENTITY_ID: u64;
67 const PRIMARY_KEY: &'static str;
68 const FIELDS: &'static [&'static str];
69 const INDEXES: &'static [&'static IndexSpec];
70
71 fn key(&self) -> Key;
72 fn primary_key(&self) -> Self::PrimaryKey;
73}
74
75pub trait StoreKind: Kind {
80 type Canister: CanisterKind;
81}
82
83pub trait TypeKind:
93 Kind
94 + View
95 + Clone
96 + Default
97 + Serialize
98 + DeserializeOwned
99 + Sanitize
100 + Validate
101 + Visitable
102 + PartialEq
103{
104}
105
106impl<T> TypeKind for T where
107 T: Kind
108 + View
109 + Clone
110 + Default
111 + DeserializeOwned
112 + PartialEq
113 + Serialize
114 + Sanitize
115 + Validate
116 + Visitable
117{
118}
119
120pub trait FieldValues {
129 fn get_value(&self, field: &str) -> Option<Value>;
130}
131
132pub trait FieldValue {
137 fn to_value(&self) -> Value {
138 Value::Unsupported
139 }
140}
141
142impl FieldValue for &str {
143 fn to_value(&self) -> Value {
144 Value::Text((*self).to_string())
145 }
146}
147
148impl FieldValue for String {
149 fn to_value(&self) -> Value {
150 Value::Text(self.clone())
151 }
152}
153
154impl<T: FieldValue + Clone> FieldValue for &T {
155 fn to_value(&self) -> Value {
156 (*self).clone().to_value()
157 }
158}
159
160impl<T: FieldValue> FieldValue for Option<T> {
161 fn to_value(&self) -> Value {
162 match self {
163 Some(v) => v.to_value(),
164 None => Value::None,
165 }
166 }
167}
168
169impl<T: FieldValue> FieldValue for Vec<T> {
170 fn to_value(&self) -> Value {
171 Value::List(self.iter().map(FieldValue::to_value).collect())
172 }
173}
174
175impl<T: FieldValue> FieldValue for Box<T> {
176 fn to_value(&self) -> Value {
177 (**self).to_value()
178 }
179}
180
181#[macro_export]
183macro_rules! impl_field_value {
184 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
185 $(
186 impl FieldValue for $type {
187 fn to_value(&self) -> Value {
188 Value::$variant((*self).into())
189 }
190 }
191 )*
192 };
193}
194
195impl_field_value!(
196 i8 => Int,
197 i16 => Int,
198 i32 => Int,
199 i64 => Int,
200 u8 => Uint,
201 u16 => Uint,
202 u32 => Uint,
203 u64 => Uint,
204 bool => Bool,
205);
206
207pub trait Filterable {
212 type Filter: FilterKind;
213 type ListFilter: FilterKind;
214}
215
216macro_rules! impl_filterable {
217 ( $( $type:ty => $filter:path, $list_filter:path );* $(;)? ) => {
219 $(
220 impl Filterable for $type {
221 type Filter = $filter;
222 type ListFilter = $list_filter;
223 }
224 )*
225 };
226}
227
228impl_filterable! {
229 bool => BoolEqualityFilterKind, BoolListFilterKind;
230 i8 => Int64RangeFilterKind, IntListFilterKind;
231 i16 => Int64RangeFilterKind, IntListFilterKind;
232 i32 => Int64RangeFilterKind, IntListFilterKind;
233 i64 => Int64RangeFilterKind, IntListFilterKind;
234
235 u8 => Nat64RangeFilterKind, NatListFilterKind;
236 u16 => Nat64RangeFilterKind, NatListFilterKind;
237 u32 => Nat64RangeFilterKind, NatListFilterKind;
238 u64 => Nat64RangeFilterKind, NatListFilterKind;
239
240 String => TextFilterKind, TextListFilterKind;
241}
242
243pub trait Inner<T> {
252 fn inner(&self) -> &T;
253 fn into_inner(self) -> T;
254}
255
256#[macro_export]
258macro_rules! impl_inner {
259 ($($type:ty),*) => {
260 $(
261 impl Inner<$type> for $type {
262 fn inner(&self) -> &$type {
263 &self
264 }
265 fn into_inner(self) -> $type {
266 self
267 }
268 }
269 )*
270 };
271}
272
273impl_inner!(
274 bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
275);
276
277pub trait Path {
285 const PATH: &'static str;
286}
287
288pub trait Sanitizer<T: ?Sized> {
294 fn sanitize(&self, value: T) -> T;
296}
297
298pub trait Validator<T: ?Sized> {
304 fn validate(&self, value: &T) -> Result<(), String>;
305}