icydb_core/traits/
mod.rs

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
13// re-exports of other traits
14// for the standard traits::X pattern
15pub 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
38/// ------------------------
39/// KIND TRAITS
40/// the Schema uses the term "Node" but when they're built it's "Kind"
41/// ------------------------
42
43///
44/// Kind
45///
46
47pub trait Kind: Path + 'static {}
48
49impl<T> Kind for T where T: Path + 'static {}
50
51///
52/// CanisterKind
53///
54
55pub trait CanisterKind: Kind {}
56
57///
58/// EntityKind
59///
60
61pub trait EntityKind: Kind + TypeKind + FieldValues {
62    type PrimaryKey: Copy + Into<Key>;
63    type Store: StoreKind;
64    type Canister: CanisterKind; // Self::Store::Canister shortcut
65
66    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
75///
76/// StoreKind
77///
78
79pub trait StoreKind: Kind {
80    type Canister: CanisterKind;
81}
82
83/// ------------------------
84/// TYPE TRAITS
85/// ------------------------
86
87///
88/// TypeKind
89/// any data type
90///
91
92pub 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
120/// ------------------------
121/// OTHER TRAITS
122/// ------------------------
123
124///
125/// FieldValues
126///
127
128pub trait FieldValues {
129    fn get_value(&self, field: &str) -> Option<Value>;
130}
131
132///
133/// FieldValue
134///
135
136pub 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// impl_field_value
167#[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
192///
193/// Filterable
194///
195
196pub trait Filterable {
197    type Filter: FilterKind;
198    type ListFilter: FilterKind;
199}
200
201macro_rules! impl_filterable {
202    // Case 1: type => scalar_filter, list_filter
203    ( $( $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
228///
229/// Inner
230/// for Newtypes to get the innermost value
231///
232/// DO NOT REMOVE - its been added and removed twice already, NumCast
233/// is a pain to use and won't work for half our types
234///
235
236pub trait Inner<T> {
237    fn inner(&self) -> &T;
238    fn into_inner(self) -> T;
239}
240
241// impl_inner
242#[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
262///
263/// Path
264///
265/// any node created via a macro has a Path
266/// ie. design::game::rarity::Rarity
267///
268
269pub trait Path {
270    const PATH: &'static str;
271}
272
273///
274/// Sanitizer
275/// transforms a value into a sanitized version
276///
277
278pub trait Sanitizer<T: ?Sized> {
279    /// Takes ownership of `value` and returns a sanitized version.
280    fn sanitize(&self, value: T) -> T;
281}
282
283///
284/// Validator
285/// allows a node to validate different types of primitives
286///
287
288pub trait Validator<T: ?Sized> {
289    fn validate(&self, value: &T) -> Result<(), String>;
290}