1#[macro_use]
2mod macros;
3mod view;
4mod visitor;
5
6pub use view::*;
7pub use visitor::*;
8
9pub use canic_cdk::structures::storable::Storable;
12pub use num_traits::{FromPrimitive as NumFromPrimitive, NumCast, ToPrimitive as NumToPrimitive};
13pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
14pub use std::{
15 cmp::{Eq, Ordering, PartialEq},
16 convert::{AsRef, From, Into},
17 default::Default,
18 fmt::{Debug, Display},
19 hash::Hash,
20 iter::IntoIterator,
21 ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign},
22 str::FromStr,
23};
24
25use crate::{
26 IndexSpec, Key, Value,
27 db::primitives::{
28 BoolEqualityFilterKind, BoolListFilterKind, FilterKind, Int64RangeFilterKind,
29 IntListFilterKind, Nat64RangeFilterKind, NatListFilterKind, TextFilterKind,
30 TextListFilterKind,
31 },
32};
33
34pub trait Kind: Path + 'static {}
44
45impl<T> Kind for T where T: Path + 'static {}
46
47pub trait CanisterKind: Kind {}
52
53pub trait EntityKind: Kind + TypeKind + FieldValues {
58 type PrimaryKey: Copy + Into<Key>;
59 type Store: StoreKind;
60 type Canister: CanisterKind; const ENTITY_ID: u64;
63 const PRIMARY_KEY: &'static str;
64 const FIELDS: &'static [&'static str];
65 const INDEXES: &'static [&'static IndexSpec];
66
67 fn key(&self) -> Key;
68 fn primary_key(&self) -> Self::PrimaryKey;
69 fn set_primary_key(&mut self, key: Self::PrimaryKey);
70}
71
72pub trait StoreKind: Kind {
77 type Canister: CanisterKind;
78}
79
80pub trait TypeKind:
90 Kind
91 + View
92 + Clone
93 + Default
94 + Serialize
95 + DeserializeOwned
96 + Sanitize
97 + Validate
98 + Visitable
99 + PartialEq
100{
101}
102
103impl<T> TypeKind for T where
104 T: Kind
105 + View
106 + Clone
107 + Default
108 + DeserializeOwned
109 + PartialEq
110 + Serialize
111 + Sanitize
112 + Validate
113 + Visitable
114{
115}
116
117pub trait FieldValues {
126 fn get_value(&self, field: &str) -> Option<Value>;
127}
128
129pub trait FieldValue {
134 fn to_value(&self) -> Value {
135 Value::Unsupported
136 }
137}
138
139impl FieldValue for &str {
140 fn to_value(&self) -> Value {
141 Value::Text((*self).to_string())
142 }
143}
144
145impl FieldValue for String {
146 fn to_value(&self) -> Value {
147 Value::Text(self.clone())
148 }
149}
150
151impl<T: FieldValue + Clone> FieldValue for &T {
152 fn to_value(&self) -> Value {
153 (*self).clone().to_value()
154 }
155}
156
157impl<T: FieldValue> FieldValue for Option<T> {
158 fn to_value(&self) -> Value {
159 match self {
160 Some(v) => v.to_value(),
161 None => Value::None,
162 }
163 }
164}
165
166impl<T: FieldValue> FieldValue for Vec<T> {
167 fn to_value(&self) -> Value {
168 Value::List(self.iter().map(FieldValue::to_value).collect())
169 }
170}
171
172impl<T: FieldValue> FieldValue for Box<T> {
173 fn to_value(&self) -> Value {
174 (**self).to_value()
175 }
176}
177
178#[macro_export]
180macro_rules! impl_field_value {
181 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
182 $(
183 impl FieldValue for $type {
184 fn to_value(&self) -> Value {
185 Value::$variant((*self).into())
186 }
187 }
188 )*
189 };
190}
191
192impl_field_value!(
193 i8 => Int,
194 i16 => Int,
195 i32 => Int,
196 i64 => Int,
197 u8 => Uint,
198 u16 => Uint,
199 u32 => Uint,
200 u64 => Uint,
201 bool => Bool,
202);
203
204pub trait Filterable {
209 type Filter: FilterKind;
210 type ListFilter: FilterKind;
211}
212
213macro_rules! impl_filterable {
214 ( $( $type:ty => $filter:path, $list_filter:path );* $(;)? ) => {
216 $(
217 impl Filterable for $type {
218 type Filter = $filter;
219 type ListFilter = $list_filter;
220 }
221 )*
222 };
223}
224
225impl_filterable! {
226 bool => BoolEqualityFilterKind, BoolListFilterKind;
227 i8 => Int64RangeFilterKind, IntListFilterKind;
228 i16 => Int64RangeFilterKind, IntListFilterKind;
229 i32 => Int64RangeFilterKind, IntListFilterKind;
230 i64 => Int64RangeFilterKind, IntListFilterKind;
231
232 u8 => Nat64RangeFilterKind, NatListFilterKind;
233 u16 => Nat64RangeFilterKind, NatListFilterKind;
234 u32 => Nat64RangeFilterKind, NatListFilterKind;
235 u64 => Nat64RangeFilterKind, NatListFilterKind;
236
237 String => TextFilterKind, TextListFilterKind;
238}
239
240pub trait FromKey: Copy {
247 fn try_from_key(key: Key) -> Option<Self>;
248}
249
250#[macro_export]
251macro_rules! impl_from_key_int {
252 ( $( $ty:ty ),* $(,)? ) => {
253 $(
254 impl FromKey for $ty {
255 fn try_from_key(key: Key) -> Option<Self> {
256 match key {
257 Key::Int(v) => Self::try_from(v).ok(),
258 _ => None,
259 }
260 }
261 }
262 )*
263 };
264}
265
266#[macro_export]
267macro_rules! impl_from_key_uint {
268 ( $( $ty:ty ),* $(,)? ) => {
269 $(
270 impl FromKey for $ty {
271 fn try_from_key(key: Key) -> Option<Self> {
272 match key {
273 Key::Uint(v) => Self::try_from(v).ok(),
274 _ => None,
275 }
276 }
277 }
278 )*
279 };
280}
281
282impl_from_key_int!(i8, i16, i32, i64);
283impl_from_key_uint!(u8, u16, u32, u64);
284
285pub trait Inner<T> {
294 fn inner(&self) -> &T;
295 fn into_inner(self) -> T;
296}
297
298#[macro_export]
300macro_rules! impl_inner {
301 ($($type:ty),*) => {
302 $(
303 impl Inner<$type> for $type {
304 fn inner(&self) -> &$type {
305 &self
306 }
307 fn into_inner(self) -> $type {
308 self
309 }
310 }
311 )*
312 };
313}
314
315impl_inner!(
316 bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
317);
318
319pub trait Path {
327 const PATH: &'static str;
328}
329
330pub trait Sanitizer<T> {
336 fn sanitize(&self, value: &mut T) -> Result<(), String>;
341}
342
343pub trait Validator<T: ?Sized> {
350 fn validate(&self, value: &T) -> Result<(), String>;
352}