Skip to main content

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::FromKey;
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    const MODEL: &'static crate::model::entity::EntityModel;
63
64    fn key(&self) -> Key;
65    fn primary_key(&self) -> Self::PrimaryKey;
66    fn set_primary_key(&mut self, key: Self::PrimaryKey);
67}
68
69///
70/// StoreKind
71///
72
73pub trait StoreKind: Kind {
74    type Canister: CanisterKind;
75}
76
77/// ------------------------
78/// TYPE TRAITS
79/// ------------------------
80
81///
82/// TypeKind
83/// any data type
84///
85
86pub trait TypeKind:
87    Kind
88    + View
89    + Clone
90    + Default
91    + Serialize
92    + DeserializeOwned
93    + Sanitize
94    + Validate
95    + Visitable
96    + PartialEq
97{
98}
99
100impl<T> TypeKind for T where
101    T: Kind
102        + View
103        + Clone
104        + Default
105        + DeserializeOwned
106        + PartialEq
107        + Serialize
108        + Sanitize
109        + Validate
110        + Visitable
111{
112}
113
114/// ------------------------
115/// OTHER TRAITS
116/// ------------------------
117
118///
119/// FieldValues
120///
121
122pub trait FieldValues {
123    fn get_value(&self, field: &str) -> Option<Value>;
124}
125
126///
127/// FieldValue
128///
129
130pub trait FieldValue {
131    fn to_value(&self) -> Value {
132        Value::Unsupported
133    }
134}
135
136impl FieldValue for &str {
137    fn to_value(&self) -> Value {
138        Value::Text((*self).to_string())
139    }
140}
141
142impl FieldValue for String {
143    fn to_value(&self) -> Value {
144        Value::Text(self.clone())
145    }
146}
147
148impl<T: FieldValue + Clone> FieldValue for &T {
149    fn to_value(&self) -> Value {
150        (*self).clone().to_value()
151    }
152}
153
154impl<T: FieldValue> FieldValue for Option<T> {
155    fn to_value(&self) -> Value {
156        match self {
157            Some(v) => v.to_value(),
158            None => Value::None,
159        }
160    }
161}
162
163impl<T: FieldValue> FieldValue for Vec<T> {
164    fn to_value(&self) -> Value {
165        Value::List(self.iter().map(FieldValue::to_value).collect())
166    }
167}
168
169impl<T: FieldValue> FieldValue for Box<T> {
170    fn to_value(&self) -> Value {
171        (**self).to_value()
172    }
173}
174
175// impl_field_value
176#[macro_export]
177macro_rules! impl_field_value {
178    ( $( $type:ty => $variant:ident ),* $(,)? ) => {
179        $(
180            impl FieldValue for $type {
181                fn to_value(&self) -> Value {
182                    Value::$variant((*self).into())
183                }
184            }
185        )*
186    };
187}
188
189impl_field_value!(
190    i8 => Int,
191    i16 => Int,
192    i32 => Int,
193    i64 => Int,
194    u8 => Uint,
195    u16 => Uint,
196    u32 => Uint,
197    u64 => Uint,
198    bool => Bool,
199);
200
201///
202/// Inner
203/// for Newtypes to get the innermost value
204///
205/// DO NOT REMOVE - its been added and removed twice already, NumCast
206/// is a pain to use and won't work for half our types
207///
208
209pub trait Inner<T> {
210    fn inner(&self) -> &T;
211    fn into_inner(self) -> T;
212}
213
214// impl_inner
215#[macro_export]
216macro_rules! impl_inner {
217    ($($type:ty),*) => {
218        $(
219            impl Inner<$type> for $type {
220                fn inner(&self) -> &$type {
221                    &self
222                }
223                fn into_inner(self) -> $type {
224                    self
225                }
226            }
227        )*
228    };
229}
230
231impl_inner!(
232    bool, f32, f64, i8, i16, i32, i64, i128, String, u8, u16, u32, u64, u128
233);
234
235///
236/// Path
237///
238/// any node created via a macro has a Path
239/// ie. design::game::rarity::Rarity
240///
241
242pub trait Path {
243    const PATH: &'static str;
244}
245
246///
247/// Sanitizer
248/// transforms a value into a sanitized version
249///
250
251pub trait Sanitizer<T> {
252    /// Apply in-place sanitization.
253    ///
254    /// - `Ok(())` means success (possibly with issues recorded by the caller)
255    /// - `Err(String)` means a fatal sanitization failure
256    fn sanitize(&self, value: &mut T) -> Result<(), String>;
257}
258
259///
260/// Validator
261/// allows a node to validate different types of primitives
262/// ?Sized so we can operate on str
263///
264
265pub trait Validator<T: ?Sized> {
266    fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
267}