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 FieldValue for Vec<Value> {
161 fn to_value(&self) -> Value {
162 Value::List(self.clone())
163 }
164}
165
166#[macro_export]
168macro_rules! impl_field_value {
169 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
170 $(
171 impl FieldValue for $type {
172 fn to_value(&self) -> Value {
173 Value::$variant((*self).into())
174 }
175 }
176 )*
177 };
178}
179
180impl_field_value!(
181 i8 => Int,
182 i16 => Int,
183 i32 => Int,
184 i64 => Int,
185 u8 => Uint,
186 u16 => Uint,
187 u32 => Uint,
188 u64 => Uint,
189 bool => Bool,
190);
191
192pub trait Filterable {
197 type Filter: FilterKind;
198 type ListFilter: FilterKind;
199}
200
201macro_rules! impl_filterable {
202 ( $( $type:ty => $filter:path, $list_filter:path );* $(;)? ) => {
204 $(
205 impl Filterable for $type {
206 type Filter = $filter;
207 type ListFilter = $list_filter;
208 }
209 )*
210 };
211}
212
213impl_filterable! {
214 bool => BoolEqualityFilterKind, BoolListFilterKind;
215 i8 => Int64RangeFilterKind, IntListFilterKind;
216 i16 => Int64RangeFilterKind, IntListFilterKind;
217 i32 => Int64RangeFilterKind, IntListFilterKind;
218 i64 => Int64RangeFilterKind, IntListFilterKind;
219
220 u8 => Nat64RangeFilterKind, NatListFilterKind;
221 u16 => Nat64RangeFilterKind, NatListFilterKind;
222 u32 => Nat64RangeFilterKind, NatListFilterKind;
223 u64 => Nat64RangeFilterKind, NatListFilterKind;
224
225 String => TextFilterKind, TextListFilterKind;
226}
227
228pub trait Inner<T> {
237 fn inner(&self) -> &T;
238 fn into_inner(self) -> T;
239}
240
241#[macro_export]
243macro_rules! impl_inner {
244 ($($type:ty),*) => {
245 $(
246 impl Inner<$type> for $type {
247 fn inner(&self) -> &$type {
248 &self
249 }
250 fn into_inner(self) -> $type {
251 self
252 }
253 }
254 )*
255 };
256}
257
258impl_inner!(
259 bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
260);
261
262pub trait Path {
270 const PATH: &'static str;
271}
272
273pub trait Sanitizer<T: ?Sized> {
279 fn sanitize(&self, value: T) -> T;
281}
282
283pub trait Validator<T: ?Sized> {
289 fn validate(&self, value: &T) -> Result<(), String>;
290}