1#[macro_use]
8mod macros;
9mod atomic;
10mod numeric_value;
11mod visitor;
12
13use crate::{
14 error::InternalError,
15 model::field::{FieldKind, FieldStorageDecode},
16 prelude::*,
17 types::{EntityTag, Id},
18 value::{Value, ValueEnum},
19 visitor::VisitorContext,
20};
21use std::collections::{BTreeMap, BTreeSet};
22
23pub use atomic::*;
24pub use numeric_value::*;
25pub use visitor::*;
26
27pub use canic_cdk::structures::storable::Storable;
32pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
33pub use std::{
34 cmp::{Eq, Ordering, PartialEq},
35 convert::From,
36 default::Default,
37 fmt::Debug,
38 hash::Hash,
39 ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign},
40};
41
42pub trait Path {
56 const PATH: &'static str;
57}
58
59pub trait Kind: Path + 'static {}
65impl<T> Kind for T where T: Path + 'static {}
66
67pub trait CanisterKind: Kind {
73 const COMMIT_MEMORY_ID: u8;
75}
76
77pub trait StoreKind: Kind {
83 type Canister: CanisterKind;
84}
85
86pub trait EntityKey {
108 type Key: Copy + Debug + Eq + Ord + KeyValueCodec + EntityKeyBytes + 'static;
109}
110
111pub trait EntityKeyBytes {
116 const BYTE_LEN: usize;
118
119 fn write_bytes(&self, out: &mut [u8]);
121}
122
123macro_rules! impl_entity_key_bytes_numeric {
124 ($($ty:ty),* $(,)?) => {
125 $(
126 impl EntityKeyBytes for $ty {
127 const BYTE_LEN: usize = ::core::mem::size_of::<Self>();
128
129 fn write_bytes(&self, out: &mut [u8]) {
130 assert_eq!(out.len(), Self::BYTE_LEN);
131 out.copy_from_slice(&self.to_be_bytes());
132 }
133 }
134 )*
135 };
136}
137
138impl_entity_key_bytes_numeric!(i8, i16, i32, i64, u8, u16, u32, u64);
139
140impl EntityKeyBytes for () {
141 const BYTE_LEN: usize = 0;
142
143 fn write_bytes(&self, out: &mut [u8]) {
144 assert_eq!(out.len(), Self::BYTE_LEN);
145 }
146}
147
148pub trait KeyValueCodec {
158 fn to_key_value(&self) -> Value;
159
160 #[must_use]
161 fn from_key_value(value: &Value) -> Option<Self>
162 where
163 Self: Sized;
164}
165
166impl<T> KeyValueCodec for T
167where
168 T: ValueSurfaceDecode + ValueSurfaceEncode,
169{
170 fn to_key_value(&self) -> Value {
171 self.to_value()
172 }
173
174 fn from_key_value(value: &Value) -> Option<Self> {
175 Self::from_value(value)
176 }
177}
178
179pub trait ValueSurfaceEncode {
189 fn to_value(&self) -> Value;
190}
191
192pub trait ValueSurfaceDecode {
201 #[must_use]
202 fn from_value(value: &Value) -> Option<Self>
203 where
204 Self: Sized;
205}
206
207pub fn value_surface_to_value<T>(value: &T) -> Value
214where
215 T: ?Sized + ValueSurfaceEncode,
216{
217 value.to_value()
218}
219
220#[must_use]
227pub fn value_surface_from_value<T>(value: &Value) -> Option<T>
228where
229 T: ValueSurfaceDecode,
230{
231 T::from_value(value)
232}
233
234pub trait PersistedByKindCodec: Sized {
245 fn encode_persisted_slot_payload_by_kind(
247 &self,
248 kind: FieldKind,
249 field_name: &'static str,
250 ) -> Result<Vec<u8>, InternalError>;
251
252 fn decode_persisted_option_slot_payload_by_kind(
256 bytes: &[u8],
257 kind: FieldKind,
258 field_name: &'static str,
259 ) -> Result<Option<Self>, InternalError>;
260}
261
262pub trait PersistedStructuredFieldCodec {
271 fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
273
274 fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
276 where
277 Self: Sized;
278}
279
280pub trait EntitySchema: EntityKey {
291 const NAME: &'static str;
292 const MODEL: &'static EntityModel;
293}
294
295pub trait EntityPlacement {
309 type Store: StoreKind;
310 type Canister: CanisterKind;
311}
312
313pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
323 const ENTITY_TAG: EntityTag;
324}
325
326pub trait EntityValue: EntityKey + FieldProjection + Sized {
344 fn id(&self) -> Id<Self>;
345}
346
347pub struct EntityCreateMaterialization<E> {
356 entity: E,
357 authored_slots: Vec<usize>,
358}
359
360impl<E> EntityCreateMaterialization<E> {
361 #[must_use]
363 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
364 Self {
365 entity,
366 authored_slots,
367 }
368 }
369
370 #[must_use]
372 pub fn into_entity(self) -> E {
373 self.entity
374 }
375
376 #[must_use]
378 pub const fn authored_slots(&self) -> &[usize] {
379 self.authored_slots.as_slice()
380 }
381}
382
383pub trait EntityCreateInput: Sized {
392 type Entity: EntityValue + Default;
393
394 fn materialize_create(self) -> EntityCreateMaterialization<Self::Entity>;
396}
397
398pub trait EntityCreateType: EntityValue {
408 type Create: EntityCreateInput<Entity = Self>;
409}
410
411pub trait SingletonEntity: EntityValue {}
413
414pub trait TypeKind:
432 Kind + Clone + Default + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
433{
434}
435
436impl<T> TypeKind for T where
437 T: Kind + Clone + Default + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
438{
439}
440
441pub trait FieldTypeMeta {
450 const KIND: FieldKind;
452
453 const STORAGE_DECODE: FieldStorageDecode;
455}
456
457pub trait PersistedFieldMetaCodec: FieldTypeMeta + Sized {
468 fn encode_persisted_slot_payload_by_meta(
471 &self,
472 field_name: &'static str,
473 ) -> Result<Vec<u8>, InternalError>;
474
475 fn decode_persisted_slot_payload_by_meta(
478 bytes: &[u8],
479 field_name: &'static str,
480 ) -> Result<Self, InternalError>;
481
482 fn encode_persisted_option_slot_payload_by_meta(
485 value: &Option<Self>,
486 field_name: &'static str,
487 ) -> Result<Vec<u8>, InternalError>;
488
489 fn decode_persisted_option_slot_payload_by_meta(
492 bytes: &[u8],
493 field_name: &'static str,
494 ) -> Result<Option<Self>, InternalError>;
495}
496
497impl<T> FieldTypeMeta for Option<T>
498where
499 T: FieldTypeMeta,
500{
501 const KIND: FieldKind = T::KIND;
502 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
503}
504
505impl<T> FieldTypeMeta for Box<T>
506where
507 T: FieldTypeMeta,
508{
509 const KIND: FieldKind = T::KIND;
510 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
511}
512
513impl<T> FieldTypeMeta for Vec<T>
517where
518 T: FieldTypeMeta,
519{
520 const KIND: FieldKind = FieldKind::List(&T::KIND);
521 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
522}
523
524impl<T> FieldTypeMeta for BTreeSet<T>
525where
526 T: FieldTypeMeta,
527{
528 const KIND: FieldKind = FieldKind::Set(&T::KIND);
529 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
530}
531
532impl<K, V> FieldTypeMeta for BTreeMap<K, V>
533where
534 K: FieldTypeMeta,
535 V: FieldTypeMeta,
536{
537 const KIND: FieldKind = FieldKind::Map {
538 key: &K::KIND,
539 value: &V::KIND,
540 };
541 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
542}
543
544pub trait Collection {
557 type Item;
558
559 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
561 where
562 Self: 'a;
563
564 fn iter(&self) -> Self::Iter<'_>;
566
567 fn len(&self) -> usize;
569
570 fn is_empty(&self) -> bool {
572 self.len() == 0
573 }
574}
575
576pub trait MapCollection {
585 type Key;
586 type Value;
587
588 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
590 where
591 Self: 'a;
592
593 fn iter(&self) -> Self::Iter<'_>;
595
596 fn len(&self) -> usize;
598
599 fn is_empty(&self) -> bool {
601 self.len() == 0
602 }
603}
604
605impl<T> Collection for Vec<T> {
606 type Item = T;
607 type Iter<'a>
608 = std::slice::Iter<'a, T>
609 where
610 Self: 'a;
611
612 fn iter(&self) -> Self::Iter<'_> {
613 self.as_slice().iter()
614 }
615
616 fn len(&self) -> usize {
617 self.as_slice().len()
618 }
619}
620
621impl<T> Collection for BTreeSet<T> {
622 type Item = T;
623 type Iter<'a>
624 = std::collections::btree_set::Iter<'a, T>
625 where
626 Self: 'a;
627
628 fn iter(&self) -> Self::Iter<'_> {
629 self.iter()
630 }
631
632 fn len(&self) -> usize {
633 self.len()
634 }
635}
636
637impl<K, V> MapCollection for BTreeMap<K, V> {
638 type Key = K;
639 type Value = V;
640 type Iter<'a>
641 = std::collections::btree_map::Iter<'a, K, V>
642 where
643 Self: 'a;
644
645 fn iter(&self) -> Self::Iter<'_> {
646 self.iter()
647 }
648
649 fn len(&self) -> usize {
650 self.len()
651 }
652}
653
654pub trait EnumValue {
655 fn to_value_enum(&self) -> ValueEnum;
656}
657
658pub trait FieldProjection {
659 fn get_value_by_index(&self, index: usize) -> Option<Value>;
661}
662
663#[derive(Clone, Copy, Debug, Eq, PartialEq)]
671pub enum ValueSurfaceKind {
672 Atomic,
674
675 Structured {
678 queryable: bool,
680 },
681}
682
683impl ValueSurfaceKind {
684 #[must_use]
685 pub const fn is_queryable(self) -> bool {
686 match self {
687 Self::Atomic => true,
688 Self::Structured { queryable } => queryable,
689 }
690 }
691}
692
693pub trait ValueSurfaceMeta {
702 fn kind() -> ValueSurfaceKind
703 where
704 Self: Sized;
705}
706
707pub fn value_surface_collection_to_value<C>(collection: &C) -> Value
716where
717 C: Collection,
718 C::Item: ValueSurfaceEncode,
719{
720 Value::List(
721 collection
722 .iter()
723 .map(ValueSurfaceEncode::to_value)
724 .collect(),
725 )
726}
727
728#[must_use]
737pub fn value_surface_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
738where
739 T: ValueSurfaceDecode,
740{
741 let Value::List(values) = value else {
742 return None;
743 };
744
745 let mut out = Vec::with_capacity(values.len());
746 for value in values {
747 out.push(T::from_value(value)?);
748 }
749
750 Some(out)
751}
752
753#[must_use]
762pub fn value_surface_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
763where
764 T: Ord + ValueSurfaceDecode,
765{
766 let Value::List(values) = value else {
767 return None;
768 };
769
770 let mut out = BTreeSet::new();
771 for value in values {
772 let item = T::from_value(value)?;
773 if !out.insert(item) {
774 return None;
775 }
776 }
777
778 Some(out)
779}
780
781pub fn value_surface_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
791where
792 M: MapCollection,
793 M::Key: ValueSurfaceEncode,
794 M::Value: ValueSurfaceEncode,
795{
796 let mut entries: Vec<(Value, Value)> = map
797 .iter()
798 .map(|(key, value)| {
799 (
800 ValueSurfaceEncode::to_value(key),
801 ValueSurfaceEncode::to_value(value),
802 )
803 })
804 .collect();
805
806 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
807 debug_assert!(false, "invalid map field value for {path}: {err}");
808 return Value::Map(entries);
809 }
810
811 Value::sort_map_entries_in_place(entries.as_mut_slice());
812
813 for i in 1..entries.len() {
814 let (left_key, _) = &entries[i - 1];
815 let (right_key, _) = &entries[i];
816 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
817 debug_assert!(
818 false,
819 "duplicate map key in {path} after value-surface canonicalization",
820 );
821 break;
822 }
823 }
824
825 Value::Map(entries)
826}
827
828#[must_use]
837pub fn value_surface_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
838where
839 K: Ord + ValueSurfaceDecode,
840 V: ValueSurfaceDecode,
841{
842 let Value::Map(entries) = value else {
843 return None;
844 };
845
846 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
847 if normalized.as_slice() != entries.as_slice() {
848 return None;
849 }
850
851 let mut map = BTreeMap::new();
852 for (entry_key, entry_value) in normalized {
853 let key = K::from_value(&entry_key)?;
854 let value = V::from_value(&entry_value)?;
855 map.insert(key, value);
856 }
857
858 Some(map)
859}
860
861#[must_use]
870pub fn value_surface_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
871where
872 I: Into<T>,
873{
874 entries.into_iter().map(Into::into).collect()
875}
876
877#[must_use]
886pub fn value_surface_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
887where
888 I: Into<T>,
889 T: Ord,
890{
891 entries.into_iter().map(Into::into).collect()
892}
893
894#[must_use]
903pub fn value_surface_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
904where
905 IK: Into<K>,
906 IV: Into<V>,
907 K: Ord,
908{
909 entries
910 .into_iter()
911 .map(|(key, value)| (key.into(), value.into()))
912 .collect()
913}
914
915#[must_use]
924pub fn value_surface_into<T, U>(value: U) -> T
925where
926 U: Into<T>,
927{
928 value.into()
929}
930
931impl ValueSurfaceMeta for &str {
932 fn kind() -> ValueSurfaceKind {
933 ValueSurfaceKind::Atomic
934 }
935}
936
937impl ValueSurfaceEncode for &str {
938 fn to_value(&self) -> Value {
939 Value::Text((*self).to_string())
940 }
941}
942
943impl ValueSurfaceDecode for &str {
944 fn from_value(_value: &Value) -> Option<Self> {
945 None
946 }
947}
948
949impl ValueSurfaceMeta for String {
950 fn kind() -> ValueSurfaceKind {
951 ValueSurfaceKind::Atomic
952 }
953}
954
955impl ValueSurfaceEncode for String {
956 fn to_value(&self) -> Value {
957 Value::Text(self.clone())
958 }
959}
960
961impl ValueSurfaceDecode for String {
962 fn from_value(value: &Value) -> Option<Self> {
963 match value {
964 Value::Text(v) => Some(v.clone()),
965 _ => None,
966 }
967 }
968}
969
970impl<T: ValueSurfaceMeta> ValueSurfaceMeta for Option<T> {
971 fn kind() -> ValueSurfaceKind {
972 T::kind()
973 }
974}
975
976impl<T: ValueSurfaceEncode> ValueSurfaceEncode for Option<T> {
977 fn to_value(&self) -> Value {
978 match self {
979 Some(v) => v.to_value(),
980 None => Value::Null,
981 }
982 }
983}
984
985impl<T: ValueSurfaceDecode> ValueSurfaceDecode for Option<T> {
986 fn from_value(value: &Value) -> Option<Self> {
987 if matches!(value, Value::Null) {
988 return Some(None);
989 }
990
991 T::from_value(value).map(Some)
992 }
993}
994
995impl<T: ValueSurfaceMeta> ValueSurfaceMeta for Box<T> {
996 fn kind() -> ValueSurfaceKind {
997 T::kind()
998 }
999}
1000
1001impl<T: ValueSurfaceEncode> ValueSurfaceEncode for Box<T> {
1002 fn to_value(&self) -> Value {
1003 (**self).to_value()
1004 }
1005}
1006
1007impl<T: ValueSurfaceDecode> ValueSurfaceDecode for Box<T> {
1008 fn from_value(value: &Value) -> Option<Self> {
1009 T::from_value(value).map(Self::new)
1010 }
1011}
1012
1013impl<T> ValueSurfaceMeta for Vec<T> {
1014 fn kind() -> ValueSurfaceKind {
1015 ValueSurfaceKind::Structured { queryable: true }
1016 }
1017}
1018
1019impl<T: ValueSurfaceEncode> ValueSurfaceEncode for Vec<T> {
1020 fn to_value(&self) -> Value {
1021 value_surface_collection_to_value(self)
1022 }
1023}
1024
1025impl<T: ValueSurfaceDecode> ValueSurfaceDecode for Vec<T> {
1026 fn from_value(value: &Value) -> Option<Self> {
1027 value_surface_vec_from_value(value)
1028 }
1029}
1030
1031impl<T> ValueSurfaceMeta for BTreeSet<T>
1032where
1033 T: Ord,
1034{
1035 fn kind() -> ValueSurfaceKind {
1036 ValueSurfaceKind::Structured { queryable: true }
1037 }
1038}
1039
1040impl<T> ValueSurfaceEncode for BTreeSet<T>
1041where
1042 T: Ord + ValueSurfaceEncode,
1043{
1044 fn to_value(&self) -> Value {
1045 value_surface_collection_to_value(self)
1046 }
1047}
1048
1049impl<T> ValueSurfaceDecode for BTreeSet<T>
1050where
1051 T: Ord + ValueSurfaceDecode,
1052{
1053 fn from_value(value: &Value) -> Option<Self> {
1054 value_surface_btree_set_from_value(value)
1055 }
1056}
1057
1058impl<K, V> ValueSurfaceMeta for BTreeMap<K, V>
1059where
1060 K: Ord,
1061{
1062 fn kind() -> ValueSurfaceKind {
1063 ValueSurfaceKind::Structured { queryable: true }
1064 }
1065}
1066
1067impl<K, V> ValueSurfaceEncode for BTreeMap<K, V>
1068where
1069 K: Ord + ValueSurfaceEncode,
1070 V: ValueSurfaceEncode,
1071{
1072 fn to_value(&self) -> Value {
1073 value_surface_map_collection_to_value(self, std::any::type_name::<Self>())
1074 }
1075}
1076
1077impl<K, V> ValueSurfaceDecode for BTreeMap<K, V>
1078where
1079 K: Ord + ValueSurfaceDecode,
1080 V: ValueSurfaceDecode,
1081{
1082 fn from_value(value: &Value) -> Option<Self> {
1083 value_surface_btree_map_from_value(value)
1084 }
1085}
1086
1087#[macro_export]
1089macro_rules! impl_field_value {
1090 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
1091 $(
1092 impl ValueSurfaceMeta for $type {
1093 fn kind() -> ValueSurfaceKind {
1094 ValueSurfaceKind::Atomic
1095 }
1096 }
1097
1098 impl ValueSurfaceEncode for $type {
1099 fn to_value(&self) -> Value {
1100 Value::$variant((*self).into())
1101 }
1102 }
1103
1104 impl ValueSurfaceDecode for $type {
1105 fn from_value(value: &Value) -> Option<Self> {
1106 match value {
1107 Value::$variant(v) => (*v).try_into().ok(),
1108 _ => None,
1109 }
1110 }
1111 }
1112 )*
1113 };
1114}
1115
1116impl_field_value!(
1117 i8 => Int,
1118 i16 => Int,
1119 i32 => Int,
1120 i64 => Int,
1121 u8 => Uint,
1122 u16 => Uint,
1123 u32 => Uint,
1124 u64 => Uint,
1125 bool => Bool,
1126);
1127
1128pub trait Inner<T> {
1139 fn inner(&self) -> &T;
1140 fn into_inner(self) -> T;
1141}
1142
1143impl<T> Inner<T> for T
1144where
1145 T: Atomic,
1146{
1147 fn inner(&self) -> &T {
1148 self
1149 }
1150
1151 fn into_inner(self) -> T {
1152 self
1153 }
1154}
1155
1156pub trait Repr {
1163 type Inner;
1164
1165 fn repr(&self) -> Self::Inner;
1166 fn from_repr(inner: Self::Inner) -> Self;
1167}
1168
1169pub trait Sanitizer<T> {
1180 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1181
1182 fn sanitize_with_context(
1183 &self,
1184 value: &mut T,
1185 ctx: &mut dyn VisitorContext,
1186 ) -> Result<(), String> {
1187 let _ = ctx;
1188
1189 self.sanitize(value)
1190 }
1191}
1192
1193pub trait Validator<T: ?Sized> {
1200 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1201}