1#[macro_use]
8mod macros;
9mod atomic;
10mod numeric_value;
11mod visitor;
12
13use crate::{
14 model::field::{FieldKind, FieldStorageDecode},
15 prelude::*,
16 types::{EntityTag, Id},
17 value::{Value, ValueEnum},
18 visitor::VisitorContext,
19};
20use std::collections::{BTreeMap, BTreeSet};
21
22pub use atomic::*;
23pub use numeric_value::*;
24pub use visitor::*;
25
26pub use canic_cdk::structures::storable::Storable;
31pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
32pub use std::{
33 cmp::{Eq, Ordering, PartialEq},
34 convert::From,
35 default::Default,
36 fmt::Debug,
37 hash::Hash,
38 ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign},
39};
40
41pub trait Path {
55 const PATH: &'static str;
56}
57
58pub trait Kind: Path + 'static {}
64impl<T> Kind for T where T: Path + 'static {}
65
66pub trait CanisterKind: Kind {
72 const COMMIT_MEMORY_ID: u8;
74}
75
76pub trait StoreKind: Kind {
82 type Canister: CanisterKind;
83}
84
85pub trait EntityKey {
107 type Key: Copy + Debug + Eq + Ord + KeyValueCodec + EntityKeyBytes + 'static;
108}
109
110pub trait EntityKeyBytes {
115 const BYTE_LEN: usize;
117
118 fn write_bytes(&self, out: &mut [u8]);
120}
121
122macro_rules! impl_entity_key_bytes_numeric {
123 ($($ty:ty),* $(,)?) => {
124 $(
125 impl EntityKeyBytes for $ty {
126 const BYTE_LEN: usize = ::core::mem::size_of::<Self>();
127
128 fn write_bytes(&self, out: &mut [u8]) {
129 assert_eq!(out.len(), Self::BYTE_LEN);
130 out.copy_from_slice(&self.to_be_bytes());
131 }
132 }
133 )*
134 };
135}
136
137impl_entity_key_bytes_numeric!(i8, i16, i32, i64, u8, u16, u32, u64);
138
139impl EntityKeyBytes for () {
140 const BYTE_LEN: usize = 0;
141
142 fn write_bytes(&self, out: &mut [u8]) {
143 assert_eq!(out.len(), Self::BYTE_LEN);
144 }
145}
146
147pub trait KeyValueCodec {
157 fn to_key_value(&self) -> Value;
158
159 #[must_use]
160 fn from_key_value(value: &Value) -> Option<Self>
161 where
162 Self: Sized;
163}
164
165impl<T> KeyValueCodec for T
166where
167 T: ValueCodec,
168{
169 fn to_key_value(&self) -> Value {
170 self.to_value()
171 }
172
173 fn from_key_value(value: &Value) -> Option<Self> {
174 Self::from_value(value)
175 }
176}
177
178pub trait ValueCodec {
188 fn to_value(&self) -> Value;
189
190 #[must_use]
191 fn from_value(value: &Value) -> Option<Self>
192 where
193 Self: Sized;
194}
195
196pub trait EntitySchema: EntityKey {
207 const NAME: &'static str;
208 const MODEL: &'static EntityModel;
209}
210
211pub trait EntityPlacement {
225 type Store: StoreKind;
226 type Canister: CanisterKind;
227}
228
229pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
239 const ENTITY_TAG: EntityTag;
240}
241
242pub trait EntityValue: EntityKey + FieldProjection + Sized {
260 fn id(&self) -> Id<Self>;
261}
262
263pub struct EntityCreateMaterialization<E> {
272 entity: E,
273 authored_slots: Vec<usize>,
274}
275
276impl<E> EntityCreateMaterialization<E> {
277 #[must_use]
279 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
280 Self {
281 entity,
282 authored_slots,
283 }
284 }
285
286 #[must_use]
288 pub fn into_entity(self) -> E {
289 self.entity
290 }
291
292 #[must_use]
294 pub const fn authored_slots(&self) -> &[usize] {
295 self.authored_slots.as_slice()
296 }
297}
298
299pub trait EntityCreateInput: Sized {
308 type Entity: EntityValue + Default;
309
310 fn materialize_create(self) -> EntityCreateMaterialization<Self::Entity>;
312}
313
314pub trait EntityCreateType: EntityValue {
324 type Create: EntityCreateInput<Entity = Self>;
325}
326
327pub trait SingletonEntity: EntityValue {}
329
330pub trait TypeKind:
348 Kind + Clone + Default + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
349{
350}
351
352impl<T> TypeKind for T where
353 T: Kind + Clone + Default + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
354{
355}
356
357pub trait FieldTypeMeta {
366 const KIND: FieldKind;
368
369 const STORAGE_DECODE: FieldStorageDecode;
371}
372
373impl<T> FieldTypeMeta for Option<T>
374where
375 T: FieldTypeMeta,
376{
377 const KIND: FieldKind = T::KIND;
378 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
379}
380
381impl<T> FieldTypeMeta for Box<T>
382where
383 T: FieldTypeMeta,
384{
385 const KIND: FieldKind = T::KIND;
386 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
387}
388
389impl<T> FieldTypeMeta for Vec<T>
393where
394 T: FieldTypeMeta,
395{
396 const KIND: FieldKind = FieldKind::List(&T::KIND);
397 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
398}
399
400impl<T> FieldTypeMeta for BTreeSet<T>
401where
402 T: FieldTypeMeta,
403{
404 const KIND: FieldKind = FieldKind::Set(&T::KIND);
405 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
406}
407
408impl<K, V> FieldTypeMeta for BTreeMap<K, V>
409where
410 K: FieldTypeMeta,
411 V: FieldTypeMeta,
412{
413 const KIND: FieldKind = FieldKind::Map {
414 key: &K::KIND,
415 value: &V::KIND,
416 };
417 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
418}
419
420pub trait Collection {
433 type Item;
434
435 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
437 where
438 Self: 'a;
439
440 fn iter(&self) -> Self::Iter<'_>;
442
443 fn len(&self) -> usize;
445
446 fn is_empty(&self) -> bool {
448 self.len() == 0
449 }
450}
451
452pub trait MapCollection {
461 type Key;
462 type Value;
463
464 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
466 where
467 Self: 'a;
468
469 fn iter(&self) -> Self::Iter<'_>;
471
472 fn len(&self) -> usize;
474
475 fn is_empty(&self) -> bool {
477 self.len() == 0
478 }
479}
480
481impl<T> Collection for Vec<T> {
482 type Item = T;
483 type Iter<'a>
484 = std::slice::Iter<'a, T>
485 where
486 Self: 'a;
487
488 fn iter(&self) -> Self::Iter<'_> {
489 self.as_slice().iter()
490 }
491
492 fn len(&self) -> usize {
493 self.as_slice().len()
494 }
495}
496
497impl<T> Collection for BTreeSet<T> {
498 type Item = T;
499 type Iter<'a>
500 = std::collections::btree_set::Iter<'a, T>
501 where
502 Self: 'a;
503
504 fn iter(&self) -> Self::Iter<'_> {
505 self.iter()
506 }
507
508 fn len(&self) -> usize {
509 self.len()
510 }
511}
512
513impl<K, V> MapCollection for BTreeMap<K, V> {
514 type Key = K;
515 type Value = V;
516 type Iter<'a>
517 = std::collections::btree_map::Iter<'a, K, V>
518 where
519 Self: 'a;
520
521 fn iter(&self) -> Self::Iter<'_> {
522 self.iter()
523 }
524
525 fn len(&self) -> usize {
526 self.len()
527 }
528}
529
530pub trait EnumValue {
531 fn to_value_enum(&self) -> ValueEnum;
532}
533
534pub trait FieldProjection {
535 fn get_value_by_index(&self, index: usize) -> Option<Value>;
537}
538
539#[derive(Clone, Copy, Debug, Eq, PartialEq)]
547pub enum ValueSurfaceKind {
548 Atomic,
550
551 Structured {
554 queryable: bool,
556 },
557}
558
559impl ValueSurfaceKind {
560 #[must_use]
561 pub const fn is_queryable(self) -> bool {
562 match self {
563 Self::Atomic => true,
564 Self::Structured { queryable } => queryable,
565 }
566 }
567}
568
569pub trait ValueSurfaceMeta {
578 fn kind() -> ValueSurfaceKind
579 where
580 Self: Sized;
581}
582
583pub fn value_codec_collection_to_value<C>(collection: &C) -> Value
592where
593 C: Collection,
594 C::Item: ValueCodec,
595{
596 Value::List(collection.iter().map(ValueCodec::to_value).collect())
597}
598
599#[must_use]
608pub fn value_codec_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
609where
610 T: ValueCodec,
611{
612 let Value::List(values) = value else {
613 return None;
614 };
615
616 let mut out = Vec::with_capacity(values.len());
617 for value in values {
618 out.push(T::from_value(value)?);
619 }
620
621 Some(out)
622}
623
624#[must_use]
633pub fn value_codec_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
634where
635 T: Ord + ValueCodec,
636{
637 let Value::List(values) = value else {
638 return None;
639 };
640
641 let mut out = BTreeSet::new();
642 for value in values {
643 let item = T::from_value(value)?;
644 if !out.insert(item) {
645 return None;
646 }
647 }
648
649 Some(out)
650}
651
652pub fn value_codec_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
662where
663 M: MapCollection,
664 M::Key: ValueCodec,
665 M::Value: ValueCodec,
666{
667 let mut entries: Vec<(Value, Value)> = map
668 .iter()
669 .map(|(key, value)| (ValueCodec::to_value(key), ValueCodec::to_value(value)))
670 .collect();
671
672 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
673 debug_assert!(false, "invalid map field value for {path}: {err}");
674 return Value::Map(entries);
675 }
676
677 Value::sort_map_entries_in_place(entries.as_mut_slice());
678
679 for i in 1..entries.len() {
680 let (left_key, _) = &entries[i - 1];
681 let (right_key, _) = &entries[i];
682 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
683 debug_assert!(
684 false,
685 "duplicate map key in {path} after ValueCodec::to_value canonicalization",
686 );
687 break;
688 }
689 }
690
691 Value::Map(entries)
692}
693
694#[must_use]
703pub fn value_codec_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
704where
705 K: Ord + ValueCodec,
706 V: ValueCodec,
707{
708 let Value::Map(entries) = value else {
709 return None;
710 };
711
712 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
713 if normalized.as_slice() != entries.as_slice() {
714 return None;
715 }
716
717 let mut map = BTreeMap::new();
718 for (entry_key, entry_value) in normalized {
719 let key = K::from_value(&entry_key)?;
720 let value = V::from_value(&entry_value)?;
721 map.insert(key, value);
722 }
723
724 Some(map)
725}
726
727#[must_use]
736pub fn value_codec_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
737where
738 I: Into<T>,
739{
740 entries.into_iter().map(Into::into).collect()
741}
742
743#[must_use]
752pub fn value_codec_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
753where
754 I: Into<T>,
755 T: Ord,
756{
757 entries.into_iter().map(Into::into).collect()
758}
759
760#[must_use]
769pub fn value_codec_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
770where
771 IK: Into<K>,
772 IV: Into<V>,
773 K: Ord,
774{
775 entries
776 .into_iter()
777 .map(|(key, value)| (key.into(), value.into()))
778 .collect()
779}
780
781#[must_use]
790pub fn value_codec_into<T, U>(value: U) -> T
791where
792 U: Into<T>,
793{
794 value.into()
795}
796
797impl ValueSurfaceMeta for &str {
798 fn kind() -> ValueSurfaceKind {
799 ValueSurfaceKind::Atomic
800 }
801}
802
803impl ValueCodec for &str {
804 fn to_value(&self) -> Value {
805 Value::Text((*self).to_string())
806 }
807
808 fn from_value(_value: &Value) -> Option<Self> {
809 None
810 }
811}
812
813impl ValueSurfaceMeta for String {
814 fn kind() -> ValueSurfaceKind {
815 ValueSurfaceKind::Atomic
816 }
817}
818
819impl ValueCodec for String {
820 fn to_value(&self) -> Value {
821 Value::Text(self.clone())
822 }
823
824 fn from_value(value: &Value) -> Option<Self> {
825 match value {
826 Value::Text(v) => Some(v.clone()),
827 _ => None,
828 }
829 }
830}
831
832impl<T: ValueSurfaceMeta> ValueSurfaceMeta for Option<T> {
833 fn kind() -> ValueSurfaceKind {
834 T::kind()
835 }
836}
837
838impl<T: ValueCodec> ValueCodec for Option<T> {
839 fn to_value(&self) -> Value {
840 match self {
841 Some(v) => v.to_value(),
842 None => Value::Null,
843 }
844 }
845
846 fn from_value(value: &Value) -> Option<Self> {
847 if matches!(value, Value::Null) {
848 return Some(None);
849 }
850
851 T::from_value(value).map(Some)
852 }
853}
854
855impl<T: ValueSurfaceMeta> ValueSurfaceMeta for Box<T> {
856 fn kind() -> ValueSurfaceKind {
857 T::kind()
858 }
859}
860
861impl<T: ValueCodec> ValueCodec for Box<T> {
862 fn to_value(&self) -> Value {
863 (**self).to_value()
864 }
865
866 fn from_value(value: &Value) -> Option<Self> {
867 T::from_value(value).map(Self::new)
868 }
869}
870
871impl<T> ValueSurfaceMeta for Vec<T> {
872 fn kind() -> ValueSurfaceKind {
873 ValueSurfaceKind::Structured { queryable: true }
874 }
875}
876
877impl<T: ValueCodec> ValueCodec for Vec<T> {
878 fn to_value(&self) -> Value {
879 value_codec_collection_to_value(self)
880 }
881
882 fn from_value(value: &Value) -> Option<Self> {
883 value_codec_vec_from_value(value)
884 }
885}
886
887impl<T> ValueSurfaceMeta for BTreeSet<T>
888where
889 T: Ord,
890{
891 fn kind() -> ValueSurfaceKind {
892 ValueSurfaceKind::Structured { queryable: true }
893 }
894}
895
896impl<T> ValueCodec for BTreeSet<T>
897where
898 T: Ord + ValueCodec,
899{
900 fn to_value(&self) -> Value {
901 value_codec_collection_to_value(self)
902 }
903
904 fn from_value(value: &Value) -> Option<Self> {
905 value_codec_btree_set_from_value(value)
906 }
907}
908
909impl<K, V> ValueSurfaceMeta for BTreeMap<K, V>
910where
911 K: Ord,
912{
913 fn kind() -> ValueSurfaceKind {
914 ValueSurfaceKind::Structured { queryable: true }
915 }
916}
917
918impl<K, V> ValueCodec for BTreeMap<K, V>
919where
920 K: Ord + ValueCodec,
921 V: ValueCodec,
922{
923 fn to_value(&self) -> Value {
924 value_codec_map_collection_to_value(self, std::any::type_name::<Self>())
925 }
926
927 fn from_value(value: &Value) -> Option<Self> {
928 value_codec_btree_map_from_value(value)
929 }
930}
931
932#[macro_export]
934macro_rules! impl_field_value {
935 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
936 $(
937 impl ValueSurfaceMeta for $type {
938 fn kind() -> ValueSurfaceKind {
939 ValueSurfaceKind::Atomic
940 }
941 }
942
943 impl ValueCodec for $type {
944 fn to_value(&self) -> Value {
945 Value::$variant((*self).into())
946 }
947
948 fn from_value(value: &Value) -> Option<Self> {
949 match value {
950 Value::$variant(v) => (*v).try_into().ok(),
951 _ => None,
952 }
953 }
954 }
955 )*
956 };
957}
958
959impl_field_value!(
960 i8 => Int,
961 i16 => Int,
962 i32 => Int,
963 i64 => Int,
964 u8 => Uint,
965 u16 => Uint,
966 u32 => Uint,
967 u64 => Uint,
968 bool => Bool,
969);
970
971pub trait Inner<T> {
982 fn inner(&self) -> &T;
983 fn into_inner(self) -> T;
984}
985
986impl<T> Inner<T> for T
987where
988 T: Atomic,
989{
990 fn inner(&self) -> &T {
991 self
992 }
993
994 fn into_inner(self) -> T {
995 self
996 }
997}
998
999pub trait Repr {
1006 type Inner;
1007
1008 fn repr(&self) -> Self::Inner;
1009 fn from_repr(inner: Self::Inner) -> Self;
1010}
1011
1012pub trait Sanitizer<T> {
1023 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1024
1025 fn sanitize_with_context(
1026 &self,
1027 value: &mut T,
1028 ctx: &mut dyn VisitorContext,
1029 ) -> Result<(), String> {
1030 let _ = ctx;
1031
1032 self.sanitize(value)
1033 }
1034}
1035
1036pub trait Validator<T: ?Sized> {
1043 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1044}