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 db::primitives::{
27 BoolEqualityFilterKind, BoolListFilterKind, FilterKind, Int64RangeFilterKind,
28 IntListFilterKind, Nat64RangeFilterKind, NatListFilterKind, TextFilterKind,
29 TextListFilterKind,
30 },
31 prelude::*,
32 visitor::VisitorContext,
33};
34
35pub trait Kind: Path + 'static {}
45
46impl<T> Kind for T where T: Path + 'static {}
47
48pub trait CanisterKind: Kind {}
53
54pub trait EntityKind: Kind + TypeKind + FieldValues {
59 type PrimaryKey: Copy + Into<Key>;
60 type Store: StoreKind;
61 type Canister: CanisterKind; const ENTITY_ID: u64;
64 const PRIMARY_KEY: &'static str;
65 const FIELDS: &'static [&'static str];
66 const INDEXES: &'static [&'static IndexModel];
67
68 fn key(&self) -> Key;
69 fn primary_key(&self) -> Self::PrimaryKey;
70 fn set_primary_key(&mut self, key: Self::PrimaryKey);
71}
72
73pub trait StoreKind: Kind {
78 type Canister: CanisterKind;
79}
80
81pub trait TypeKind:
91 Kind
92 + View
93 + Clone
94 + Default
95 + Serialize
96 + DeserializeOwned
97 + Sanitize
98 + Validate
99 + Visitable
100 + PartialEq
101{
102}
103
104impl<T> TypeKind for T where
105 T: Kind
106 + View
107 + Clone
108 + Default
109 + DeserializeOwned
110 + PartialEq
111 + Serialize
112 + Sanitize
113 + Validate
114 + Visitable
115{
116}
117
118pub trait FieldValues {
127 fn get_value(&self, field: &str) -> Option<Value>;
128}
129
130pub trait FieldValue {
135 fn to_value(&self) -> Value {
136 Value::Unsupported
137 }
138}
139
140impl FieldValue for &str {
141 fn to_value(&self) -> Value {
142 Value::Text((*self).to_string())
143 }
144}
145
146impl FieldValue for String {
147 fn to_value(&self) -> Value {
148 Value::Text(self.clone())
149 }
150}
151
152impl<T: FieldValue + Clone> FieldValue for &T {
153 fn to_value(&self) -> Value {
154 (*self).clone().to_value()
155 }
156}
157
158impl<T: FieldValue> FieldValue for Option<T> {
159 fn to_value(&self) -> Value {
160 match self {
161 Some(v) => v.to_value(),
162 None => Value::None,
163 }
164 }
165}
166
167impl<T: FieldValue> FieldValue for Vec<T> {
168 fn to_value(&self) -> Value {
169 Value::List(self.iter().map(FieldValue::to_value).collect())
170 }
171}
172
173impl<T: FieldValue> FieldValue for Box<T> {
174 fn to_value(&self) -> Value {
175 (**self).to_value()
176 }
177}
178
179#[macro_export]
181macro_rules! impl_field_value {
182 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
183 $(
184 impl FieldValue for $type {
185 fn to_value(&self) -> Value {
186 Value::$variant((*self).into())
187 }
188 }
189 )*
190 };
191}
192
193impl_field_value!(
194 i8 => Int,
195 i16 => Int,
196 i32 => Int,
197 i64 => Int,
198 u8 => Uint,
199 u16 => Uint,
200 u32 => Uint,
201 u64 => Uint,
202 bool => Bool,
203);
204
205pub trait Filterable {
210 type Filter: FilterKind;
211 type ListFilter: FilterKind;
212}
213
214macro_rules! impl_filterable {
215 ( $( $type:ty => $filter:path, $list_filter:path );* $(;)? ) => {
217 $(
218 impl Filterable for $type {
219 type Filter = $filter;
220 type ListFilter = $list_filter;
221 }
222 )*
223 };
224}
225
226impl_filterable! {
227 bool => BoolEqualityFilterKind, BoolListFilterKind;
228 i8 => Int64RangeFilterKind, IntListFilterKind;
229 i16 => Int64RangeFilterKind, IntListFilterKind;
230 i32 => Int64RangeFilterKind, IntListFilterKind;
231 i64 => Int64RangeFilterKind, IntListFilterKind;
232
233 u8 => Nat64RangeFilterKind, NatListFilterKind;
234 u16 => Nat64RangeFilterKind, NatListFilterKind;
235 u32 => Nat64RangeFilterKind, NatListFilterKind;
236 u64 => Nat64RangeFilterKind, NatListFilterKind;
237
238 String => TextFilterKind, TextListFilterKind;
239}
240
241pub trait FromKey: Copy {
248 fn try_from_key(key: Key) -> Option<Self>;
249}
250
251#[macro_export]
252macro_rules! impl_from_key_int {
253 ( $( $ty:ty ),* $(,)? ) => {
254 $(
255 impl FromKey for $ty {
256 fn try_from_key(key: Key) -> Option<Self> {
257 match key {
258 Key::Int(v) => Self::try_from(v).ok(),
259 _ => None,
260 }
261 }
262 }
263 )*
264 };
265}
266
267#[macro_export]
268macro_rules! impl_from_key_uint {
269 ( $( $ty:ty ),* $(,)? ) => {
270 $(
271 impl FromKey for $ty {
272 fn try_from_key(key: Key) -> Option<Self> {
273 match key {
274 Key::Uint(v) => Self::try_from(v).ok(),
275 _ => None,
276 }
277 }
278 }
279 )*
280 };
281}
282
283impl_from_key_int!(i8, i16, i32, i64);
284impl_from_key_uint!(u8, u16, u32, u64);
285
286pub trait Inner<T> {
295 fn inner(&self) -> &T;
296 fn into_inner(self) -> T;
297}
298
299#[macro_export]
301macro_rules! impl_inner {
302 ($($type:ty),*) => {
303 $(
304 impl Inner<$type> for $type {
305 fn inner(&self) -> &$type {
306 &self
307 }
308 fn into_inner(self) -> $type {
309 self
310 }
311 }
312 )*
313 };
314}
315
316impl_inner!(
317 bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
318);
319
320pub trait Path {
328 const PATH: &'static str;
329}
330
331pub trait Sanitizer<T> {
337 fn sanitize(&self, value: &mut T) -> Result<(), String>;
342}
343
344pub trait Validator<T: ?Sized> {
351 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
352}