1#[macro_use]
8mod macros;
9mod numeric_value;
10mod visitor;
11
12use crate::{
13 error::InternalError,
14 model::field::{FieldKind, FieldModel, FieldStorageDecode},
15 prelude::*,
16 types::{EntityTag, Id},
17 value::{StorageKey, StorageKeyEncodeError, Value, ValueEnum},
18 visitor::VisitorContext,
19};
20use std::collections::{BTreeMap, BTreeSet};
21
22pub use numeric_value::*;
23pub use visitor::*;
24
25pub use canic_cdk::structures::storable::Storable;
30pub use serde::{Deserialize, Serialize, de::DeserializeOwned};
31pub use std::{
32 cmp::{Eq, Ordering, PartialEq},
33 convert::From,
34 default::Default,
35 fmt::Debug,
36 hash::Hash,
37 ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign},
38};
39
40pub trait Path {
54 const PATH: &'static str;
55}
56
57pub trait Kind: Path + 'static {}
63impl<T> Kind for T where T: Path + 'static {}
64
65pub trait CanisterKind: Kind {
71 const COMMIT_MEMORY_ID: u8;
73
74 const COMMIT_STABLE_KEY: &'static str;
76}
77
78pub trait StoreKind: Kind {
84 type Canister: CanisterKind;
85}
86
87pub trait EntityKey {
109 type Key: Copy
110 + Debug
111 + Eq
112 + Ord
113 + KeyValueCodec
114 + StorageKeyCodec
115 + StorageKeyDecode
116 + EntityKeyBytes
117 + 'static;
118}
119
120pub trait EntityKeyBytes {
125 const BYTE_LEN: usize;
127
128 fn write_bytes(&self, out: &mut [u8]);
130}
131
132macro_rules! impl_entity_key_bytes_numeric {
133 ($($ty:ty),* $(,)?) => {
134 $(
135 impl EntityKeyBytes for $ty {
136 const BYTE_LEN: usize = ::core::mem::size_of::<Self>();
137
138 fn write_bytes(&self, out: &mut [u8]) {
139 assert_eq!(out.len(), Self::BYTE_LEN);
140 out.copy_from_slice(&self.to_be_bytes());
141 }
142 }
143 )*
144 };
145}
146
147impl_entity_key_bytes_numeric!(i8, i16, i32, i64, u8, u16, u32, u64);
148
149impl EntityKeyBytes for () {
150 const BYTE_LEN: usize = 0;
151
152 fn write_bytes(&self, out: &mut [u8]) {
153 assert_eq!(out.len(), Self::BYTE_LEN);
154 }
155}
156
157pub trait KeyValueCodec {
167 fn to_key_value(&self) -> Value;
168
169 #[must_use]
170 fn from_key_value(value: &Value) -> Option<Self>
171 where
172 Self: Sized;
173}
174
175pub trait StorageKeyCodec {
183 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError>;
184}
185
186pub trait StorageKeyDecode: Sized {
195 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError>;
196}
197
198fn storage_key_variant_decode_failed(
199 type_name: &'static str,
200 key: StorageKey,
201 expected: &'static str,
202) -> InternalError {
203 InternalError::store_corruption(format!(
204 "storage key decode failed for `{type_name}`: expected {expected}, found {key:?}",
205 ))
206}
207
208fn storage_key_range_decode_failed(type_name: &'static str, key: StorageKey) -> InternalError {
209 InternalError::store_corruption(format!(
210 "storage key decode failed for `{type_name}`: value out of range for {key:?}",
211 ))
212}
213
214macro_rules! impl_storage_key_codec_signed {
215 ($($ty:ty),* $(,)?) => {
216 $(
217 impl StorageKeyCodec for $ty {
218 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
219 Ok(StorageKey::Int(i64::from(*self)))
220 }
221 }
222 )*
223 };
224}
225
226macro_rules! impl_storage_key_codec_unsigned {
227 ($($ty:ty),* $(,)?) => {
228 $(
229 impl StorageKeyCodec for $ty {
230 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
231 Ok(StorageKey::Nat(u64::from(*self)))
232 }
233 }
234 )*
235 };
236}
237
238impl<T> KeyValueCodec for T
239where
240 T: RuntimeValueDecode + RuntimeValueEncode,
241{
242 fn to_key_value(&self) -> Value {
243 self.to_value()
244 }
245
246 fn from_key_value(value: &Value) -> Option<Self> {
247 Self::from_value(value)
248 }
249}
250
251impl_storage_key_codec_signed!(i8, i16, i32, i64);
252impl_storage_key_codec_unsigned!(u8, u16, u32, u64);
253
254macro_rules! impl_storage_key_decode_signed {
255 ($($ty:ty),* $(,)?) => {
256 $(
257 impl StorageKeyDecode for $ty {
258 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
259 let StorageKey::Int(value) = key else {
260 return Err(storage_key_variant_decode_failed(
261 ::std::any::type_name::<Self>(),
262 key,
263 "StorageKey::Int",
264 ));
265 };
266
267 Self::try_from(value).map_err(|_| {
268 storage_key_range_decode_failed(::std::any::type_name::<Self>(), key)
269 })
270 }
271 }
272 )*
273 };
274}
275
276macro_rules! impl_storage_key_decode_unsigned {
277 ($($ty:ty),* $(,)?) => {
278 $(
279 impl StorageKeyDecode for $ty {
280 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
281 let StorageKey::Nat(value) = key else {
282 return Err(storage_key_variant_decode_failed(
283 ::std::any::type_name::<Self>(),
284 key,
285 "StorageKey::Nat",
286 ));
287 };
288
289 Self::try_from(value).map_err(|_| {
290 storage_key_range_decode_failed(::std::any::type_name::<Self>(), key)
291 })
292 }
293 }
294 )*
295 };
296}
297
298impl_storage_key_decode_signed!(i8, i16, i32, i64);
299impl_storage_key_decode_unsigned!(u8, u16, u32, u64);
300
301impl StorageKeyCodec for crate::types::Principal {
302 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
303 Ok(StorageKey::Principal(*self))
304 }
305}
306
307impl StorageKeyDecode for crate::types::Principal {
308 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
309 match key {
310 StorageKey::Principal(value) => Ok(value),
311 other => Err(storage_key_variant_decode_failed(
312 ::std::any::type_name::<Self>(),
313 other,
314 "StorageKey::Principal",
315 )),
316 }
317 }
318}
319
320impl StorageKeyCodec for crate::types::Subaccount {
321 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
322 Ok(StorageKey::Subaccount(*self))
323 }
324}
325
326impl StorageKeyDecode for crate::types::Subaccount {
327 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
328 match key {
329 StorageKey::Subaccount(value) => Ok(value),
330 other => Err(storage_key_variant_decode_failed(
331 ::std::any::type_name::<Self>(),
332 other,
333 "StorageKey::Subaccount",
334 )),
335 }
336 }
337}
338
339impl StorageKeyCodec for crate::types::Account {
340 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
341 Ok(StorageKey::Account(*self))
342 }
343}
344
345impl StorageKeyDecode for crate::types::Account {
346 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
347 match key {
348 StorageKey::Account(value) => Ok(value),
349 other => Err(storage_key_variant_decode_failed(
350 ::std::any::type_name::<Self>(),
351 other,
352 "StorageKey::Account",
353 )),
354 }
355 }
356}
357
358impl StorageKeyCodec for crate::types::Timestamp {
359 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
360 Ok(StorageKey::Timestamp(*self))
361 }
362}
363
364impl StorageKeyDecode for crate::types::Timestamp {
365 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
366 match key {
367 StorageKey::Timestamp(value) => Ok(value),
368 other => Err(storage_key_variant_decode_failed(
369 ::std::any::type_name::<Self>(),
370 other,
371 "StorageKey::Timestamp",
372 )),
373 }
374 }
375}
376
377impl StorageKeyCodec for crate::types::Ulid {
378 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
379 Ok(StorageKey::Ulid(*self))
380 }
381}
382
383impl StorageKeyDecode for crate::types::Ulid {
384 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
385 match key {
386 StorageKey::Ulid(value) => Ok(value),
387 other => Err(storage_key_variant_decode_failed(
388 ::std::any::type_name::<Self>(),
389 other,
390 "StorageKey::Ulid",
391 )),
392 }
393 }
394}
395
396impl StorageKeyCodec for () {
397 fn to_storage_key(&self) -> Result<StorageKey, StorageKeyEncodeError> {
398 Ok(StorageKey::Unit)
399 }
400}
401
402impl StorageKeyDecode for () {
403 fn from_storage_key(key: StorageKey) -> Result<Self, InternalError> {
404 match key {
405 StorageKey::Unit => Ok(()),
406 other => Err(storage_key_variant_decode_failed(
407 ::std::any::type_name::<Self>(),
408 other,
409 "StorageKey::Unit",
410 )),
411 }
412 }
413}
414
415pub trait RuntimeValueEncode {
427 fn to_value(&self) -> Value;
428}
429
430pub trait RuntimeValueDecode {
441 #[must_use]
442 fn from_value(value: &Value) -> Option<Self>
443 where
444 Self: Sized;
445}
446
447pub fn runtime_value_to_value<T>(value: &T) -> Value
456where
457 T: ?Sized + RuntimeValueEncode,
458{
459 value.to_value()
460}
461
462#[must_use]
471pub fn runtime_value_from_value<T>(value: &Value) -> Option<T>
472where
473 T: RuntimeValueDecode,
474{
475 T::from_value(value)
476}
477
478pub trait PersistedByKindCodec: Sized {
488 fn encode_persisted_slot_payload_by_kind(
490 &self,
491 kind: FieldKind,
492 field_name: &'static str,
493 ) -> Result<Vec<u8>, InternalError>;
494
495 fn decode_persisted_option_slot_payload_by_kind(
499 bytes: &[u8],
500 kind: FieldKind,
501 field_name: &'static str,
502 ) -> Result<Option<Self>, InternalError>;
503}
504
505pub trait PersistedStructuredFieldCodec {
517 fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
519
520 fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
522 where
523 Self: Sized;
524}
525
526pub trait EntitySchema: EntityKey {
537 const NAME: &'static str;
538 const MODEL: &'static EntityModel;
539}
540
541pub trait EntityPlacement {
555 type Store: StoreKind;
556 type Canister: CanisterKind;
557}
558
559pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
569 const ENTITY_TAG: EntityTag;
570}
571
572pub trait EntityValue: EntityKey + FieldProjection + Sized {
590 fn id(&self) -> Id<Self>;
591}
592
593pub struct EntityCreateMaterialization<E> {
602 entity: E,
603 authored_slots: Vec<usize>,
604}
605
606impl<E> EntityCreateMaterialization<E> {
607 #[must_use]
609 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
610 Self {
611 entity,
612 authored_slots,
613 }
614 }
615
616 #[must_use]
618 pub fn into_entity(self) -> E {
619 self.entity
620 }
621
622 #[must_use]
624 pub const fn authored_slots(&self) -> &[usize] {
625 self.authored_slots.as_slice()
626 }
627}
628
629pub trait EntityCreateInput: Sized {
638 type Entity: EntityValue;
639
640 fn materialize_create(self)
642 -> Result<EntityCreateMaterialization<Self::Entity>, InternalError>;
643}
644
645pub trait EntityCreateType: EntityValue {
655 type Create: EntityCreateInput<Entity = Self>;
656}
657
658pub trait SingletonEntity: EntityValue {}
660
661pub trait TypeKind:
679 Kind + Clone + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
680{
681}
682
683impl<T> TypeKind for T where
684 T: Kind + Clone + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
685{
686}
687
688pub trait FieldTypeMeta {
697 const KIND: FieldKind;
699
700 const STORAGE_DECODE: FieldStorageDecode;
702
703 const NESTED_FIELDS: &'static [FieldModel] = &[];
705}
706
707pub trait PersistedFieldMetaCodec: FieldTypeMeta + Sized {
718 fn encode_persisted_slot_payload_by_meta(
721 &self,
722 field_name: &'static str,
723 ) -> Result<Vec<u8>, InternalError>;
724
725 fn decode_persisted_slot_payload_by_meta(
728 bytes: &[u8],
729 field_name: &'static str,
730 ) -> Result<Self, InternalError>;
731
732 fn encode_persisted_option_slot_payload_by_meta(
735 value: &Option<Self>,
736 field_name: &'static str,
737 ) -> Result<Vec<u8>, InternalError>;
738
739 fn decode_persisted_option_slot_payload_by_meta(
742 bytes: &[u8],
743 field_name: &'static str,
744 ) -> Result<Option<Self>, InternalError>;
745}
746
747pub trait PersistedFieldSlotCodec: Sized {
757 fn encode_persisted_slot(&self, field_name: &'static str) -> Result<Vec<u8>, InternalError>;
760
761 fn decode_persisted_slot(bytes: &[u8], field_name: &'static str)
764 -> Result<Self, InternalError>;
765
766 fn encode_persisted_option_slot(
769 value: &Option<Self>,
770 field_name: &'static str,
771 ) -> Result<Vec<u8>, InternalError>;
772
773 fn decode_persisted_option_slot(
776 bytes: &[u8],
777 field_name: &'static str,
778 ) -> Result<Option<Self>, InternalError>;
779}
780
781impl<T> FieldTypeMeta for Option<T>
782where
783 T: FieldTypeMeta,
784{
785 const KIND: FieldKind = T::KIND;
786 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
787 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
788}
789
790impl<T> FieldTypeMeta for Box<T>
791where
792 T: FieldTypeMeta,
793{
794 const KIND: FieldKind = T::KIND;
795 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
796 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
797}
798
799impl<T> FieldTypeMeta for Vec<T>
803where
804 T: FieldTypeMeta,
805{
806 const KIND: FieldKind = FieldKind::List(&T::KIND);
807 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
808}
809
810impl<T> FieldTypeMeta for BTreeSet<T>
811where
812 T: FieldTypeMeta,
813{
814 const KIND: FieldKind = FieldKind::Set(&T::KIND);
815 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
816}
817
818impl<K, V> FieldTypeMeta for BTreeMap<K, V>
819where
820 K: FieldTypeMeta,
821 V: FieldTypeMeta,
822{
823 const KIND: FieldKind = FieldKind::Map {
824 key: &K::KIND,
825 value: &V::KIND,
826 };
827 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
828}
829
830pub trait Collection {
843 type Item;
844
845 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
847 where
848 Self: 'a;
849
850 fn iter(&self) -> Self::Iter<'_>;
852
853 fn len(&self) -> usize;
855
856 fn is_empty(&self) -> bool {
858 self.len() == 0
859 }
860}
861
862pub trait MapCollection {
871 type Key;
872 type Value;
873
874 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
876 where
877 Self: 'a;
878
879 fn iter(&self) -> Self::Iter<'_>;
881
882 fn len(&self) -> usize;
884
885 fn is_empty(&self) -> bool {
887 self.len() == 0
888 }
889}
890
891impl<T> Collection for Vec<T> {
892 type Item = T;
893 type Iter<'a>
894 = std::slice::Iter<'a, T>
895 where
896 Self: 'a;
897
898 fn iter(&self) -> Self::Iter<'_> {
899 self.as_slice().iter()
900 }
901
902 fn len(&self) -> usize {
903 self.as_slice().len()
904 }
905}
906
907impl<T> Collection for BTreeSet<T> {
908 type Item = T;
909 type Iter<'a>
910 = std::collections::btree_set::Iter<'a, T>
911 where
912 Self: 'a;
913
914 fn iter(&self) -> Self::Iter<'_> {
915 self.iter()
916 }
917
918 fn len(&self) -> usize {
919 self.len()
920 }
921}
922
923impl<K, V> MapCollection for BTreeMap<K, V> {
924 type Key = K;
925 type Value = V;
926 type Iter<'a>
927 = std::collections::btree_map::Iter<'a, K, V>
928 where
929 Self: 'a;
930
931 fn iter(&self) -> Self::Iter<'_> {
932 self.iter()
933 }
934
935 fn len(&self) -> usize {
936 self.len()
937 }
938}
939
940pub trait EnumValue {
941 fn to_value_enum(&self) -> ValueEnum;
942}
943
944pub trait FieldProjection {
945 fn get_value_by_index(&self, index: usize) -> Option<Value>;
947}
948
949#[derive(Clone, Copy, Debug, Eq, PartialEq)]
957pub enum RuntimeValueKind {
958 Atomic,
960
961 Structured {
964 queryable: bool,
966 },
967}
968
969impl RuntimeValueKind {
970 #[must_use]
971 pub const fn is_queryable(self) -> bool {
972 match self {
973 Self::Atomic => true,
974 Self::Structured { queryable } => queryable,
975 }
976 }
977}
978
979pub trait RuntimeValueMeta {
988 fn kind() -> RuntimeValueKind
989 where
990 Self: Sized;
991}
992
993pub fn runtime_value_collection_to_value<C>(collection: &C) -> Value
1002where
1003 C: Collection,
1004 C::Item: RuntimeValueEncode,
1005{
1006 Value::List(
1007 collection
1008 .iter()
1009 .map(RuntimeValueEncode::to_value)
1010 .collect(),
1011 )
1012}
1013
1014#[must_use]
1023pub fn runtime_value_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
1024where
1025 T: RuntimeValueDecode,
1026{
1027 let Value::List(values) = value else {
1028 return None;
1029 };
1030
1031 let mut out = Vec::with_capacity(values.len());
1032 for value in values {
1033 out.push(T::from_value(value)?);
1034 }
1035
1036 Some(out)
1037}
1038
1039#[must_use]
1048pub fn runtime_value_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
1049where
1050 T: Ord + RuntimeValueDecode,
1051{
1052 let Value::List(values) = value else {
1053 return None;
1054 };
1055
1056 let mut out = BTreeSet::new();
1057 for value in values {
1058 let item = T::from_value(value)?;
1059 if !out.insert(item) {
1060 return None;
1061 }
1062 }
1063
1064 Some(out)
1065}
1066
1067pub fn runtime_value_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
1077where
1078 M: MapCollection,
1079 M::Key: RuntimeValueEncode,
1080 M::Value: RuntimeValueEncode,
1081{
1082 let mut entries: Vec<(Value, Value)> = map
1083 .iter()
1084 .map(|(key, value)| {
1085 (
1086 RuntimeValueEncode::to_value(key),
1087 RuntimeValueEncode::to_value(value),
1088 )
1089 })
1090 .collect();
1091
1092 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
1093 debug_assert!(false, "invalid map field value for {path}: {err}");
1094 return Value::Map(entries);
1095 }
1096
1097 Value::sort_map_entries_in_place(entries.as_mut_slice());
1098
1099 for i in 1..entries.len() {
1100 let (left_key, _) = &entries[i - 1];
1101 let (right_key, _) = &entries[i];
1102 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
1103 debug_assert!(
1104 false,
1105 "duplicate map key in {path} after value-surface canonicalization",
1106 );
1107 break;
1108 }
1109 }
1110
1111 Value::Map(entries)
1112}
1113
1114#[must_use]
1123pub fn runtime_value_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
1124where
1125 K: Ord + RuntimeValueDecode,
1126 V: RuntimeValueDecode,
1127{
1128 let Value::Map(entries) = value else {
1129 return None;
1130 };
1131
1132 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
1133 if normalized.as_slice() != entries.as_slice() {
1134 return None;
1135 }
1136
1137 let mut map = BTreeMap::new();
1138 for (entry_key, entry_value) in normalized {
1139 let key = K::from_value(&entry_key)?;
1140 let value = V::from_value(&entry_value)?;
1141 map.insert(key, value);
1142 }
1143
1144 Some(map)
1145}
1146
1147#[must_use]
1156pub fn runtime_value_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
1157where
1158 I: Into<T>,
1159{
1160 entries.into_iter().map(Into::into).collect()
1161}
1162
1163#[must_use]
1172pub fn runtime_value_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
1173where
1174 I: Into<T>,
1175 T: Ord,
1176{
1177 entries.into_iter().map(Into::into).collect()
1178}
1179
1180#[must_use]
1189pub fn runtime_value_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
1190where
1191 IK: Into<K>,
1192 IV: Into<V>,
1193 K: Ord,
1194{
1195 entries
1196 .into_iter()
1197 .map(|(key, value)| (key.into(), value.into()))
1198 .collect()
1199}
1200
1201#[must_use]
1210pub fn runtime_value_into<T, U>(value: U) -> T
1211where
1212 U: Into<T>,
1213{
1214 value.into()
1215}
1216
1217impl RuntimeValueMeta for &str {
1218 fn kind() -> RuntimeValueKind {
1219 RuntimeValueKind::Atomic
1220 }
1221}
1222
1223impl RuntimeValueEncode for &str {
1224 fn to_value(&self) -> Value {
1225 Value::Text((*self).to_string())
1226 }
1227}
1228
1229impl RuntimeValueDecode for &str {
1230 fn from_value(_value: &Value) -> Option<Self> {
1231 None
1232 }
1233}
1234
1235impl RuntimeValueMeta for String {
1236 fn kind() -> RuntimeValueKind {
1237 RuntimeValueKind::Atomic
1238 }
1239}
1240
1241impl RuntimeValueEncode for String {
1242 fn to_value(&self) -> Value {
1243 Value::Text(self.clone())
1244 }
1245}
1246
1247impl RuntimeValueDecode for String {
1248 fn from_value(value: &Value) -> Option<Self> {
1249 match value {
1250 Value::Text(v) => Some(v.clone()),
1251 _ => None,
1252 }
1253 }
1254}
1255
1256impl<T: RuntimeValueMeta> RuntimeValueMeta for Option<T> {
1257 fn kind() -> RuntimeValueKind {
1258 T::kind()
1259 }
1260}
1261
1262impl<T: RuntimeValueEncode> RuntimeValueEncode for Option<T> {
1263 fn to_value(&self) -> Value {
1264 match self {
1265 Some(v) => v.to_value(),
1266 None => Value::Null,
1267 }
1268 }
1269}
1270
1271impl<T: RuntimeValueDecode> RuntimeValueDecode for Option<T> {
1272 fn from_value(value: &Value) -> Option<Self> {
1273 if matches!(value, Value::Null) {
1274 return Some(None);
1275 }
1276
1277 T::from_value(value).map(Some)
1278 }
1279}
1280
1281impl<T: RuntimeValueMeta> RuntimeValueMeta for Box<T> {
1282 fn kind() -> RuntimeValueKind {
1283 T::kind()
1284 }
1285}
1286
1287impl<T: RuntimeValueEncode> RuntimeValueEncode for Box<T> {
1288 fn to_value(&self) -> Value {
1289 (**self).to_value()
1290 }
1291}
1292
1293impl<T: RuntimeValueDecode> RuntimeValueDecode for Box<T> {
1294 fn from_value(value: &Value) -> Option<Self> {
1295 T::from_value(value).map(Self::new)
1296 }
1297}
1298
1299impl<T> RuntimeValueMeta for Vec<T> {
1300 fn kind() -> RuntimeValueKind {
1301 RuntimeValueKind::Structured { queryable: true }
1302 }
1303}
1304
1305impl<T: RuntimeValueEncode> RuntimeValueEncode for Vec<T> {
1306 fn to_value(&self) -> Value {
1307 runtime_value_collection_to_value(self)
1308 }
1309}
1310
1311impl<T: RuntimeValueDecode> RuntimeValueDecode for Vec<T> {
1312 fn from_value(value: &Value) -> Option<Self> {
1313 runtime_value_vec_from_value(value)
1314 }
1315}
1316
1317impl<T> RuntimeValueMeta for BTreeSet<T>
1318where
1319 T: Ord,
1320{
1321 fn kind() -> RuntimeValueKind {
1322 RuntimeValueKind::Structured { queryable: true }
1323 }
1324}
1325
1326impl<T> RuntimeValueEncode for BTreeSet<T>
1327where
1328 T: Ord + RuntimeValueEncode,
1329{
1330 fn to_value(&self) -> Value {
1331 runtime_value_collection_to_value(self)
1332 }
1333}
1334
1335impl<T> RuntimeValueDecode for BTreeSet<T>
1336where
1337 T: Ord + RuntimeValueDecode,
1338{
1339 fn from_value(value: &Value) -> Option<Self> {
1340 runtime_value_btree_set_from_value(value)
1341 }
1342}
1343
1344impl<K, V> RuntimeValueMeta for BTreeMap<K, V>
1345where
1346 K: Ord,
1347{
1348 fn kind() -> RuntimeValueKind {
1349 RuntimeValueKind::Structured { queryable: true }
1350 }
1351}
1352
1353impl<K, V> RuntimeValueEncode for BTreeMap<K, V>
1354where
1355 K: Ord + RuntimeValueEncode,
1356 V: RuntimeValueEncode,
1357{
1358 fn to_value(&self) -> Value {
1359 runtime_value_map_collection_to_value(self, std::any::type_name::<Self>())
1360 }
1361}
1362
1363impl<K, V> RuntimeValueDecode for BTreeMap<K, V>
1364where
1365 K: Ord + RuntimeValueDecode,
1366 V: RuntimeValueDecode,
1367{
1368 fn from_value(value: &Value) -> Option<Self> {
1369 runtime_value_btree_map_from_value(value)
1370 }
1371}
1372
1373#[macro_export]
1375macro_rules! impl_runtime_value {
1376 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
1377 $(
1378 impl RuntimeValueMeta for $type {
1379 fn kind() -> RuntimeValueKind {
1380 RuntimeValueKind::Atomic
1381 }
1382 }
1383
1384 impl RuntimeValueEncode for $type {
1385 fn to_value(&self) -> Value {
1386 Value::$variant((*self).into())
1387 }
1388 }
1389
1390 impl RuntimeValueDecode for $type {
1391 fn from_value(value: &Value) -> Option<Self> {
1392 match value {
1393 Value::$variant(v) => (*v).try_into().ok(),
1394 _ => None,
1395 }
1396 }
1397 }
1398 )*
1399 };
1400}
1401
1402impl_runtime_value!(
1403 i8 => Int,
1404 i16 => Int,
1405 i32 => Int,
1406 i64 => Int,
1407 u8 => Nat,
1408 u16 => Nat,
1409 u32 => Nat,
1410 u64 => Nat,
1411 bool => Bool,
1412);
1413
1414pub trait Inner<T> {
1425 fn inner(&self) -> &T;
1426 fn into_inner(self) -> T;
1427}
1428
1429pub trait Repr {
1436 type Inner;
1437
1438 fn repr(&self) -> Self::Inner;
1439 fn from_repr(inner: Self::Inner) -> Self;
1440}
1441
1442pub trait Sanitizer<T> {
1453 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1454
1455 fn sanitize_with_context(
1456 &self,
1457 value: &mut T,
1458 ctx: &mut dyn VisitorContext,
1459 ) -> Result<(), String> {
1460 let _ = ctx;
1461
1462 self.sanitize(value)
1463 }
1464}
1465
1466pub trait Validator<T: ?Sized> {
1473 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1474}