icydb_core/traits/
mod.rs

1#[macro_use]
2mod macros;
3mod view;
4mod visitor;
5
6pub use view::*;
7pub use visitor::*;
8
9// db traits
10pub use crate::db::traits::{FilterView, Filterable};
11
12// re-exports of other traits
13// for the standard traits::X pattern
14pub use canic_cdk::structures::storable::Storable;
15pub use num_traits::{FromPrimitive as NumFromPrimitive, NumCast, ToPrimitive as NumToPrimitive};
16pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
17pub use std::{
18    cmp::{Eq, Ordering, PartialEq},
19    convert::{AsRef, From, Into},
20    default::Default,
21    fmt::{Debug, Display},
22    hash::Hash,
23    iter::IntoIterator,
24    ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign},
25    str::FromStr,
26};
27
28use crate::{prelude::*, visitor::VisitorContext};
29
30/// ------------------------
31/// KIND TRAITS
32/// the Schema uses the term "Node" but when they're built it's "Kind"
33/// ------------------------
34
35///
36/// Kind
37///
38
39pub trait Kind: Path + 'static {}
40
41impl<T> Kind for T where T: Path + 'static {}
42
43///
44/// CanisterKind
45///
46
47pub trait CanisterKind: Kind {}
48
49///
50/// EntityKind
51///
52
53pub trait EntityKind: Kind + TypeKind + FieldValues {
54    type PrimaryKey: Copy + Into<Key>;
55    type Store: StoreKind;
56    type Canister: CanisterKind; // Self::Store::Canister shortcut
57
58    const ENTITY_NAME: &'static str;
59    const PRIMARY_KEY: &'static str;
60    const FIELDS: &'static [&'static str];
61    const INDEXES: &'static [&'static IndexModel];
62
63    fn key(&self) -> Key;
64    fn primary_key(&self) -> Self::PrimaryKey;
65    fn set_primary_key(&mut self, key: Self::PrimaryKey);
66}
67
68///
69/// StoreKind
70///
71
72pub trait StoreKind: Kind {
73    type Canister: CanisterKind;
74}
75
76/// ------------------------
77/// TYPE TRAITS
78/// ------------------------
79
80///
81/// TypeKind
82/// any data type
83///
84
85pub trait TypeKind:
86    Kind
87    + View
88    + Clone
89    + Default
90    + Serialize
91    + DeserializeOwned
92    + Sanitize
93    + Validate
94    + Visitable
95    + PartialEq
96{
97}
98
99impl<T> TypeKind for T where
100    T: Kind
101        + View
102        + Clone
103        + Default
104        + DeserializeOwned
105        + PartialEq
106        + Serialize
107        + Sanitize
108        + Validate
109        + Visitable
110{
111}
112
113/// ------------------------
114/// OTHER TRAITS
115/// ------------------------
116
117///
118/// FieldValues
119///
120
121pub trait FieldValues {
122    fn get_value(&self, field: &str) -> Option<Value>;
123}
124
125///
126/// FieldValue
127///
128
129pub trait FieldValue {
130    fn to_value(&self) -> Value {
131        Value::Unsupported
132    }
133}
134
135impl FieldValue for &str {
136    fn to_value(&self) -> Value {
137        Value::Text((*self).to_string())
138    }
139}
140
141impl FieldValue for String {
142    fn to_value(&self) -> Value {
143        Value::Text(self.clone())
144    }
145}
146
147impl<T: FieldValue + Clone> FieldValue for &T {
148    fn to_value(&self) -> Value {
149        (*self).clone().to_value()
150    }
151}
152
153impl<T: FieldValue> FieldValue for Option<T> {
154    fn to_value(&self) -> Value {
155        match self {
156            Some(v) => v.to_value(),
157            None => Value::None,
158        }
159    }
160}
161
162impl<T: FieldValue> FieldValue for Vec<T> {
163    fn to_value(&self) -> Value {
164        Value::List(self.iter().map(FieldValue::to_value).collect())
165    }
166}
167
168impl<T: FieldValue> FieldValue for Box<T> {
169    fn to_value(&self) -> Value {
170        (**self).to_value()
171    }
172}
173
174// impl_field_value
175#[macro_export]
176macro_rules! impl_field_value {
177    ( $( $type:ty => $variant:ident ),* $(,)? ) => {
178        $(
179            impl FieldValue for $type {
180                fn to_value(&self) -> Value {
181                    Value::$variant((*self).into())
182                }
183            }
184        )*
185    };
186}
187
188impl_field_value!(
189    i8 => Int,
190    i16 => Int,
191    i32 => Int,
192    i64 => Int,
193    u8 => Uint,
194    u16 => Uint,
195    u32 => Uint,
196    u64 => Uint,
197    bool => Bool,
198);
199
200///
201/// Inner
202/// for Newtypes to get the innermost value
203///
204/// DO NOT REMOVE - its been added and removed twice already, NumCast
205/// is a pain to use and won't work for half our types
206///
207
208pub trait Inner<T> {
209    fn inner(&self) -> &T;
210    fn into_inner(self) -> T;
211}
212
213// impl_inner
214#[macro_export]
215macro_rules! impl_inner {
216    ($($type:ty),*) => {
217        $(
218            impl Inner<$type> for $type {
219                fn inner(&self) -> &$type {
220                    &self
221                }
222                fn into_inner(self) -> $type {
223                    self
224                }
225            }
226        )*
227    };
228}
229
230impl_inner!(
231    bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
232);
233
234///
235/// Path
236///
237/// any node created via a macro has a Path
238/// ie. design::game::rarity::Rarity
239///
240
241pub trait Path {
242    const PATH: &'static str;
243}
244
245///
246/// Sanitizer
247/// transforms a value into a sanitized version
248///
249
250pub trait Sanitizer<T> {
251    /// Apply in-place sanitization.
252    ///
253    /// - `Ok(())` means success (possibly with issues recorded by the caller)
254    /// - `Err(String)` means a fatal sanitization failure
255    fn sanitize(&self, value: &mut T) -> Result<(), String>;
256}
257
258///
259/// Validator
260/// allows a node to validate different types of primitives
261/// ?Sized so we can operate on str
262///
263
264pub trait Validator<T: ?Sized> {
265    fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
266}