1#[macro_use]
8mod macros;
9mod numeric_value;
10mod visitor;
11
12use crate::{
13 db::{CompositePrimaryKeyValueError, PrimaryKeyComponent, PrimaryKeyValue},
14 error::InternalError,
15 model::field::{FieldKind, FieldModel, FieldStorageDecode},
16 prelude::*,
17 types::{EntityTag, Id},
18 value::{Value, ValueEnum},
19 visitor::VisitorContext,
20};
21use std::collections::{BTreeMap, BTreeSet};
22use thiserror::Error as ThisError;
23
24pub use numeric_value::*;
25pub use visitor::*;
26
27pub use ic_memory::stable_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 const COMMIT_STABLE_KEY: &'static str;
78}
79
80pub trait StoreKind: Kind {
86 type Canister: CanisterKind;
87}
88
89pub trait EntityKey {
111 type Key: Copy
112 + Debug
113 + Eq
114 + Ord
115 + KeyValueCodec
116 + PrimaryKeyCodec
117 + PrimaryKeyDecode
118 + EntityKeyBytes
119 + 'static;
120}
121
122pub trait EntityKeyBytes {
127 const BYTE_LEN: usize;
129
130 fn write_bytes(&self, out: &mut [u8]);
132}
133
134macro_rules! impl_entity_key_bytes_numeric {
135 ($($ty:ty),* $(,)?) => {
136 $(
137 impl EntityKeyBytes for $ty {
138 const BYTE_LEN: usize = ::core::mem::size_of::<Self>();
139
140 fn write_bytes(&self, out: &mut [u8]) {
141 assert_eq!(out.len(), Self::BYTE_LEN);
142 out.copy_from_slice(&self.to_be_bytes());
143 }
144 }
145 )*
146 };
147}
148
149impl_entity_key_bytes_numeric!(i8, i16, i32, i64, u8, u16, u32, u64);
150
151impl EntityKeyBytes for () {
152 const BYTE_LEN: usize = 0;
153
154 fn write_bytes(&self, out: &mut [u8]) {
155 assert_eq!(out.len(), Self::BYTE_LEN);
156 }
157}
158
159pub trait KeyValueCodec {
169 fn to_key_value(&self) -> Value;
170
171 #[must_use]
172 fn from_key_value(value: &Value) -> Option<Self>
173 where
174 Self: Sized;
175}
176
177#[derive(Debug, ThisError)]
186pub enum PrimaryKeyEncodeError {
187 #[error("primary-key component kind '{kind}' is not admitted")]
188 UnsupportedComponentKind { kind: &'static str },
189
190 #[error("composite primary key has too few components: {count} (minimum {min})")]
191 TooFewComponents { count: usize, min: usize },
192
193 #[error("composite primary key has too many components: {count} (limit {max})")]
194 TooManyComponents { count: usize, max: usize },
195
196 #[error("unit is not admitted as composite primary-key component {index}")]
197 UnitComponent { index: usize },
198}
199
200impl From<CompositePrimaryKeyValueError> for PrimaryKeyEncodeError {
201 fn from(err: CompositePrimaryKeyValueError) -> Self {
202 match err {
203 CompositePrimaryKeyValueError::TooFewComponents { count, min } => {
204 Self::TooFewComponents { count, min }
205 }
206 CompositePrimaryKeyValueError::TooManyComponents { count, max } => {
207 Self::TooManyComponents { count, max }
208 }
209 CompositePrimaryKeyValueError::UnitComponent { index } => Self::UnitComponent { index },
210 }
211 }
212}
213
214impl From<PrimaryKeyEncodeError> for InternalError {
215 fn from(err: PrimaryKeyEncodeError) -> Self {
216 Self::serialize_unsupported(err.to_string())
217 }
218}
219
220pub trait PrimaryKeyCodec {
229 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError>;
230}
231
232pub trait PrimaryKeyDecode: Sized {
242 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError>;
243}
244
245fn primary_key_variant_decode_failed(
246 type_name: &'static str,
247 key: &PrimaryKeyValue,
248 expected: &'static str,
249) -> InternalError {
250 InternalError::store_corruption(format!(
251 "primary key decode failed for `{type_name}`: expected {expected}, found {key:?}",
252 ))
253}
254
255fn primary_key_range_decode_failed(
256 type_name: &'static str,
257 key: &PrimaryKeyValue,
258) -> InternalError {
259 InternalError::store_corruption(format!(
260 "primary key decode failed for `{type_name}`: value out of range for {key:?}",
261 ))
262}
263
264macro_rules! impl_primary_key_codec_signed {
265 ($($ty:ty),* $(,)?) => {
266 $(
267 impl PrimaryKeyCodec for $ty {
268 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
269 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(i64::from(*self))))
270 }
271 }
272 )*
273 };
274}
275
276macro_rules! impl_primary_key_codec_unsigned {
277 ($($ty:ty),* $(,)?) => {
278 $(
279 impl PrimaryKeyCodec for $ty {
280 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
281 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(u64::from(*self))))
282 }
283 }
284 )*
285 };
286}
287
288impl<T> KeyValueCodec for T
289where
290 T: RuntimeValueDecode + RuntimeValueEncode,
291{
292 fn to_key_value(&self) -> Value {
293 self.to_value()
294 }
295
296 fn from_key_value(value: &Value) -> Option<Self> {
297 Self::from_value(value)
298 }
299}
300
301impl_primary_key_codec_signed!(i8, i16, i32, i64);
302impl_primary_key_codec_unsigned!(u8, u16, u32, u64);
303
304macro_rules! impl_primary_key_decode_signed {
305 ($($ty:ty),* $(,)?) => {
306 $(
307 impl PrimaryKeyDecode for $ty {
308 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
309 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(value)) = *key else {
310 return Err(primary_key_variant_decode_failed(
311 ::std::any::type_name::<Self>(),
312 key,
313 "PrimaryKeyComponent::Int64",
314 ));
315 };
316
317 Self::try_from(value).map_err(|_| {
318 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
319 })
320 }
321 }
322 )*
323 };
324}
325
326macro_rules! impl_primary_key_decode_unsigned {
327 ($($ty:ty),* $(,)?) => {
328 $(
329 impl PrimaryKeyDecode for $ty {
330 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
331 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(value)) = *key else {
332 return Err(primary_key_variant_decode_failed(
333 ::std::any::type_name::<Self>(),
334 key,
335 "PrimaryKeyComponent::Nat64",
336 ));
337 };
338
339 Self::try_from(value).map_err(|_| {
340 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
341 })
342 }
343 }
344 )*
345 };
346}
347
348impl_primary_key_decode_signed!(i8, i16, i32, i64);
349impl_primary_key_decode_unsigned!(u8, u16, u32, u64);
350
351impl PrimaryKeyCodec for crate::types::Principal {
352 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
353 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(
354 *self,
355 )))
356 }
357}
358
359impl PrimaryKeyDecode for crate::types::Principal {
360 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
361 match *key {
362 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(value)) => Ok(value),
363 _ => Err(primary_key_variant_decode_failed(
364 ::std::any::type_name::<Self>(),
365 key,
366 "PrimaryKeyComponent::Principal",
367 )),
368 }
369 }
370}
371
372impl PrimaryKeyCodec for crate::types::Subaccount {
373 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
374 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(
375 *self,
376 )))
377 }
378}
379
380impl PrimaryKeyDecode for crate::types::Subaccount {
381 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
382 match *key {
383 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(value)) => Ok(value),
384 _ => Err(primary_key_variant_decode_failed(
385 ::std::any::type_name::<Self>(),
386 key,
387 "PrimaryKeyComponent::Subaccount",
388 )),
389 }
390 }
391}
392
393impl PrimaryKeyCodec for crate::types::Account {
394 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
395 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(*self)))
396 }
397}
398
399impl PrimaryKeyDecode for crate::types::Account {
400 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
401 match *key {
402 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(value)) => Ok(value),
403 _ => Err(primary_key_variant_decode_failed(
404 ::std::any::type_name::<Self>(),
405 key,
406 "PrimaryKeyComponent::Account",
407 )),
408 }
409 }
410}
411
412impl PrimaryKeyCodec for crate::types::Timestamp {
413 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
414 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(
415 *self,
416 )))
417 }
418}
419
420impl PrimaryKeyDecode for crate::types::Timestamp {
421 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
422 match *key {
423 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(value)) => Ok(value),
424 _ => Err(primary_key_variant_decode_failed(
425 ::std::any::type_name::<Self>(),
426 key,
427 "PrimaryKeyComponent::Timestamp",
428 )),
429 }
430 }
431}
432
433impl PrimaryKeyCodec for crate::types::Ulid {
434 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
435 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(*self)))
436 }
437}
438
439impl PrimaryKeyDecode for crate::types::Ulid {
440 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
441 match *key {
442 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(value)) => Ok(value),
443 _ => Err(primary_key_variant_decode_failed(
444 ::std::any::type_name::<Self>(),
445 key,
446 "PrimaryKeyComponent::Ulid",
447 )),
448 }
449 }
450}
451
452impl PrimaryKeyCodec for () {
453 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
454 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit))
455 }
456}
457
458impl PrimaryKeyDecode for () {
459 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
460 match *key {
461 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit) => Ok(()),
462 _ => Err(primary_key_variant_decode_failed(
463 ::std::any::type_name::<Self>(),
464 key,
465 "PrimaryKeyComponent::Unit",
466 )),
467 }
468 }
469}
470
471pub trait RuntimeValueEncode {
483 fn to_value(&self) -> Value;
484}
485
486pub trait RuntimeValueDecode {
497 #[must_use]
498 fn from_value(value: &Value) -> Option<Self>
499 where
500 Self: Sized;
501}
502
503pub fn runtime_value_to_value<T>(value: &T) -> Value
512where
513 T: ?Sized + RuntimeValueEncode,
514{
515 value.to_value()
516}
517
518#[must_use]
527pub fn runtime_value_from_value<T>(value: &Value) -> Option<T>
528where
529 T: RuntimeValueDecode,
530{
531 T::from_value(value)
532}
533
534pub trait PersistedByKindCodec: Sized {
544 fn encode_persisted_slot_payload_by_kind(
546 &self,
547 kind: FieldKind,
548 field_name: &'static str,
549 ) -> Result<Vec<u8>, InternalError>;
550
551 fn decode_persisted_option_slot_payload_by_kind(
555 bytes: &[u8],
556 kind: FieldKind,
557 field_name: &'static str,
558 ) -> Result<Option<Self>, InternalError>;
559}
560
561pub trait PersistedStructuredFieldCodec {
573 fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
575
576 fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
578 where
579 Self: Sized;
580}
581
582pub trait EntitySchema: EntityKey {
593 const NAME: &'static str;
594 const MODEL: &'static EntityModel;
595}
596
597pub trait EntityPlacement {
611 type Store: StoreKind;
612 type Canister: CanisterKind;
613}
614
615pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
625 const ENTITY_TAG: EntityTag;
626}
627
628pub trait EntityValue: EntityKey + FieldProjection + Sized {
646 fn id(&self) -> Id<Self>;
647}
648
649pub struct EntityCreateMaterialization<E> {
658 entity: E,
659 authored_slots: Vec<usize>,
660}
661
662impl<E> EntityCreateMaterialization<E> {
663 #[must_use]
665 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
666 Self {
667 entity,
668 authored_slots,
669 }
670 }
671
672 #[must_use]
674 pub fn into_entity(self) -> E {
675 self.entity
676 }
677
678 #[must_use]
680 pub const fn authored_slots(&self) -> &[usize] {
681 self.authored_slots.as_slice()
682 }
683}
684
685pub trait EntityCreateInput: Sized {
694 type Entity: EntityValue;
695
696 fn materialize_create(self)
698 -> Result<EntityCreateMaterialization<Self::Entity>, InternalError>;
699}
700
701pub trait EntityCreateType: EntityValue {
711 type Create: EntityCreateInput<Entity = Self>;
712}
713
714pub trait SingletonEntity: EntityValue {}
716
717pub trait TypeKind:
735 Kind + Clone + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
736{
737}
738
739impl<T> TypeKind for T where
740 T: Kind + Clone + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
741{
742}
743
744pub trait FieldTypeMeta {
753 const KIND: FieldKind;
755
756 const STORAGE_DECODE: FieldStorageDecode;
758
759 const NESTED_FIELDS: &'static [FieldModel] = &[];
761}
762
763pub trait PersistedFieldMetaCodec: FieldTypeMeta + Sized {
774 fn encode_persisted_slot_payload_by_meta(
777 &self,
778 field_name: &'static str,
779 ) -> Result<Vec<u8>, InternalError>;
780
781 fn decode_persisted_slot_payload_by_meta(
784 bytes: &[u8],
785 field_name: &'static str,
786 ) -> Result<Self, InternalError>;
787
788 fn encode_persisted_option_slot_payload_by_meta(
791 value: &Option<Self>,
792 field_name: &'static str,
793 ) -> Result<Vec<u8>, InternalError>;
794
795 fn decode_persisted_option_slot_payload_by_meta(
798 bytes: &[u8],
799 field_name: &'static str,
800 ) -> Result<Option<Self>, InternalError>;
801}
802
803pub trait PersistedFieldSlotCodec: Sized {
813 fn encode_persisted_slot(&self, field_name: &'static str) -> Result<Vec<u8>, InternalError>;
816
817 fn decode_persisted_slot(bytes: &[u8], field_name: &'static str)
820 -> Result<Self, InternalError>;
821
822 fn encode_persisted_option_slot(
825 value: &Option<Self>,
826 field_name: &'static str,
827 ) -> Result<Vec<u8>, InternalError>;
828
829 fn decode_persisted_option_slot(
832 bytes: &[u8],
833 field_name: &'static str,
834 ) -> Result<Option<Self>, InternalError>;
835}
836
837impl<T> FieldTypeMeta for Option<T>
838where
839 T: FieldTypeMeta,
840{
841 const KIND: FieldKind = T::KIND;
842 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
843 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
844}
845
846impl<T> FieldTypeMeta for Box<T>
847where
848 T: FieldTypeMeta,
849{
850 const KIND: FieldKind = T::KIND;
851 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
852 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
853}
854
855impl<T> FieldTypeMeta for Vec<T>
859where
860 T: FieldTypeMeta,
861{
862 const KIND: FieldKind = FieldKind::List(&T::KIND);
863 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
864}
865
866impl<T> FieldTypeMeta for BTreeSet<T>
867where
868 T: FieldTypeMeta,
869{
870 const KIND: FieldKind = FieldKind::Set(&T::KIND);
871 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
872}
873
874impl<K, V> FieldTypeMeta for BTreeMap<K, V>
875where
876 K: FieldTypeMeta,
877 V: FieldTypeMeta,
878{
879 const KIND: FieldKind = FieldKind::Map {
880 key: &K::KIND,
881 value: &V::KIND,
882 };
883 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
884}
885
886pub trait Collection {
899 type Item;
900
901 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
903 where
904 Self: 'a;
905
906 fn iter(&self) -> Self::Iter<'_>;
908
909 fn len(&self) -> usize;
911
912 fn is_empty(&self) -> bool {
914 self.len() == 0
915 }
916}
917
918pub trait MapCollection {
927 type Key;
928 type Value;
929
930 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
932 where
933 Self: 'a;
934
935 fn iter(&self) -> Self::Iter<'_>;
937
938 fn len(&self) -> usize;
940
941 fn is_empty(&self) -> bool {
943 self.len() == 0
944 }
945}
946
947impl<T> Collection for Vec<T> {
948 type Item = T;
949 type Iter<'a>
950 = std::slice::Iter<'a, T>
951 where
952 Self: 'a;
953
954 fn iter(&self) -> Self::Iter<'_> {
955 self.as_slice().iter()
956 }
957
958 fn len(&self) -> usize {
959 self.as_slice().len()
960 }
961}
962
963impl<T> Collection for BTreeSet<T> {
964 type Item = T;
965 type Iter<'a>
966 = std::collections::btree_set::Iter<'a, T>
967 where
968 Self: 'a;
969
970 fn iter(&self) -> Self::Iter<'_> {
971 self.iter()
972 }
973
974 fn len(&self) -> usize {
975 self.len()
976 }
977}
978
979impl<K, V> MapCollection for BTreeMap<K, V> {
980 type Key = K;
981 type Value = V;
982 type Iter<'a>
983 = std::collections::btree_map::Iter<'a, K, V>
984 where
985 Self: 'a;
986
987 fn iter(&self) -> Self::Iter<'_> {
988 self.iter()
989 }
990
991 fn len(&self) -> usize {
992 self.len()
993 }
994}
995
996pub trait EnumValue {
997 fn to_value_enum(&self) -> ValueEnum;
998}
999
1000pub trait FieldProjection {
1001 fn get_value_by_index(&self, index: usize) -> Option<Value>;
1003}
1004
1005#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1013pub enum RuntimeValueKind {
1014 Atomic,
1016
1017 Structured {
1020 queryable: bool,
1022 },
1023}
1024
1025impl RuntimeValueKind {
1026 #[must_use]
1027 pub const fn is_queryable(self) -> bool {
1028 match self {
1029 Self::Atomic => true,
1030 Self::Structured { queryable } => queryable,
1031 }
1032 }
1033}
1034
1035pub trait RuntimeValueMeta {
1044 fn kind() -> RuntimeValueKind
1045 where
1046 Self: Sized;
1047}
1048
1049pub fn runtime_value_collection_to_value<C>(collection: &C) -> Value
1058where
1059 C: Collection,
1060 C::Item: RuntimeValueEncode,
1061{
1062 Value::List(
1063 collection
1064 .iter()
1065 .map(RuntimeValueEncode::to_value)
1066 .collect(),
1067 )
1068}
1069
1070#[must_use]
1079pub fn runtime_value_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
1080where
1081 T: RuntimeValueDecode,
1082{
1083 let Value::List(values) = value else {
1084 return None;
1085 };
1086
1087 let mut out = Vec::with_capacity(values.len());
1088 for value in values {
1089 out.push(T::from_value(value)?);
1090 }
1091
1092 Some(out)
1093}
1094
1095#[must_use]
1104pub fn runtime_value_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
1105where
1106 T: Ord + RuntimeValueDecode,
1107{
1108 let Value::List(values) = value else {
1109 return None;
1110 };
1111
1112 let mut out = BTreeSet::new();
1113 for value in values {
1114 let item = T::from_value(value)?;
1115 if !out.insert(item) {
1116 return None;
1117 }
1118 }
1119
1120 Some(out)
1121}
1122
1123pub fn runtime_value_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
1133where
1134 M: MapCollection,
1135 M::Key: RuntimeValueEncode,
1136 M::Value: RuntimeValueEncode,
1137{
1138 let mut entries: Vec<(Value, Value)> = map
1139 .iter()
1140 .map(|(key, value)| {
1141 (
1142 RuntimeValueEncode::to_value(key),
1143 RuntimeValueEncode::to_value(value),
1144 )
1145 })
1146 .collect();
1147
1148 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
1149 debug_assert!(false, "invalid map field value for {path}: {err}");
1150 return Value::Map(entries);
1151 }
1152
1153 Value::sort_map_entries_in_place(entries.as_mut_slice());
1154
1155 for i in 1..entries.len() {
1156 let (left_key, _) = &entries[i - 1];
1157 let (right_key, _) = &entries[i];
1158 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
1159 debug_assert!(
1160 false,
1161 "duplicate map key in {path} after value-surface canonicalization",
1162 );
1163 break;
1164 }
1165 }
1166
1167 Value::Map(entries)
1168}
1169
1170#[must_use]
1179pub fn runtime_value_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
1180where
1181 K: Ord + RuntimeValueDecode,
1182 V: RuntimeValueDecode,
1183{
1184 let Value::Map(entries) = value else {
1185 return None;
1186 };
1187
1188 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
1189 if normalized.as_slice() != entries.as_slice() {
1190 return None;
1191 }
1192
1193 let mut map = BTreeMap::new();
1194 for (entry_key, entry_value) in normalized {
1195 let key = K::from_value(&entry_key)?;
1196 let value = V::from_value(&entry_value)?;
1197 map.insert(key, value);
1198 }
1199
1200 Some(map)
1201}
1202
1203#[must_use]
1212pub fn runtime_value_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
1213where
1214 I: Into<T>,
1215{
1216 entries.into_iter().map(Into::into).collect()
1217}
1218
1219#[must_use]
1228pub fn runtime_value_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
1229where
1230 I: Into<T>,
1231 T: Ord,
1232{
1233 entries.into_iter().map(Into::into).collect()
1234}
1235
1236#[must_use]
1245pub fn runtime_value_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
1246where
1247 IK: Into<K>,
1248 IV: Into<V>,
1249 K: Ord,
1250{
1251 entries
1252 .into_iter()
1253 .map(|(key, value)| (key.into(), value.into()))
1254 .collect()
1255}
1256
1257#[must_use]
1266pub fn runtime_value_into<T, U>(value: U) -> T
1267where
1268 U: Into<T>,
1269{
1270 value.into()
1271}
1272
1273impl RuntimeValueMeta for &str {
1274 fn kind() -> RuntimeValueKind {
1275 RuntimeValueKind::Atomic
1276 }
1277}
1278
1279impl RuntimeValueEncode for &str {
1280 fn to_value(&self) -> Value {
1281 Value::Text((*self).to_string())
1282 }
1283}
1284
1285impl RuntimeValueDecode for &str {
1286 fn from_value(_value: &Value) -> Option<Self> {
1287 None
1288 }
1289}
1290
1291impl RuntimeValueMeta for String {
1292 fn kind() -> RuntimeValueKind {
1293 RuntimeValueKind::Atomic
1294 }
1295}
1296
1297impl RuntimeValueEncode for String {
1298 fn to_value(&self) -> Value {
1299 Value::Text(self.clone())
1300 }
1301}
1302
1303impl RuntimeValueDecode for String {
1304 fn from_value(value: &Value) -> Option<Self> {
1305 match value {
1306 Value::Text(v) => Some(v.clone()),
1307 _ => None,
1308 }
1309 }
1310}
1311
1312impl<T: RuntimeValueMeta> RuntimeValueMeta for Option<T> {
1313 fn kind() -> RuntimeValueKind {
1314 T::kind()
1315 }
1316}
1317
1318impl<T: RuntimeValueEncode> RuntimeValueEncode for Option<T> {
1319 fn to_value(&self) -> Value {
1320 match self {
1321 Some(v) => v.to_value(),
1322 None => Value::Null,
1323 }
1324 }
1325}
1326
1327impl<T: RuntimeValueDecode> RuntimeValueDecode for Option<T> {
1328 fn from_value(value: &Value) -> Option<Self> {
1329 if matches!(value, Value::Null) {
1330 return Some(None);
1331 }
1332
1333 T::from_value(value).map(Some)
1334 }
1335}
1336
1337impl<T: RuntimeValueMeta> RuntimeValueMeta for Box<T> {
1338 fn kind() -> RuntimeValueKind {
1339 T::kind()
1340 }
1341}
1342
1343impl<T: RuntimeValueEncode> RuntimeValueEncode for Box<T> {
1344 fn to_value(&self) -> Value {
1345 (**self).to_value()
1346 }
1347}
1348
1349impl<T: RuntimeValueDecode> RuntimeValueDecode for Box<T> {
1350 fn from_value(value: &Value) -> Option<Self> {
1351 T::from_value(value).map(Self::new)
1352 }
1353}
1354
1355impl<T> RuntimeValueMeta for Vec<T> {
1356 fn kind() -> RuntimeValueKind {
1357 RuntimeValueKind::Structured { queryable: true }
1358 }
1359}
1360
1361impl<T: RuntimeValueEncode> RuntimeValueEncode for Vec<T> {
1362 fn to_value(&self) -> Value {
1363 runtime_value_collection_to_value(self)
1364 }
1365}
1366
1367impl<T: RuntimeValueDecode> RuntimeValueDecode for Vec<T> {
1368 fn from_value(value: &Value) -> Option<Self> {
1369 runtime_value_vec_from_value(value)
1370 }
1371}
1372
1373impl<T> RuntimeValueMeta for BTreeSet<T>
1374where
1375 T: Ord,
1376{
1377 fn kind() -> RuntimeValueKind {
1378 RuntimeValueKind::Structured { queryable: true }
1379 }
1380}
1381
1382impl<T> RuntimeValueEncode for BTreeSet<T>
1383where
1384 T: Ord + RuntimeValueEncode,
1385{
1386 fn to_value(&self) -> Value {
1387 runtime_value_collection_to_value(self)
1388 }
1389}
1390
1391impl<T> RuntimeValueDecode for BTreeSet<T>
1392where
1393 T: Ord + RuntimeValueDecode,
1394{
1395 fn from_value(value: &Value) -> Option<Self> {
1396 runtime_value_btree_set_from_value(value)
1397 }
1398}
1399
1400impl<K, V> RuntimeValueMeta for BTreeMap<K, V>
1401where
1402 K: Ord,
1403{
1404 fn kind() -> RuntimeValueKind {
1405 RuntimeValueKind::Structured { queryable: true }
1406 }
1407}
1408
1409impl<K, V> RuntimeValueEncode for BTreeMap<K, V>
1410where
1411 K: Ord + RuntimeValueEncode,
1412 V: RuntimeValueEncode,
1413{
1414 fn to_value(&self) -> Value {
1415 runtime_value_map_collection_to_value(self, std::any::type_name::<Self>())
1416 }
1417}
1418
1419impl<K, V> RuntimeValueDecode for BTreeMap<K, V>
1420where
1421 K: Ord + RuntimeValueDecode,
1422 V: RuntimeValueDecode,
1423{
1424 fn from_value(value: &Value) -> Option<Self> {
1425 runtime_value_btree_map_from_value(value)
1426 }
1427}
1428
1429#[macro_export]
1431macro_rules! impl_runtime_value {
1432 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
1433 $(
1434 impl RuntimeValueMeta for $type {
1435 fn kind() -> RuntimeValueKind {
1436 RuntimeValueKind::Atomic
1437 }
1438 }
1439
1440 impl RuntimeValueEncode for $type {
1441 fn to_value(&self) -> Value {
1442 Value::$variant((*self).into())
1443 }
1444 }
1445
1446 impl RuntimeValueDecode for $type {
1447 fn from_value(value: &Value) -> Option<Self> {
1448 match value {
1449 Value::$variant(v) => (*v).try_into().ok(),
1450 _ => None,
1451 }
1452 }
1453 }
1454 )*
1455 };
1456}
1457
1458impl_runtime_value!(
1459 i8 => Int64,
1460 i16 => Int64,
1461 i32 => Int64,
1462 i64 => Int64,
1463 i128 => Int128,
1464 u8 => Nat64,
1465 u16 => Nat64,
1466 u32 => Nat64,
1467 u64 => Nat64,
1468 u128 => Nat128,
1469 bool => Bool,
1470);
1471
1472pub trait Inner<T> {
1483 fn inner(&self) -> &T;
1484 fn into_inner(self) -> T;
1485}
1486
1487pub trait Repr {
1494 type Inner;
1495
1496 fn repr(&self) -> Self::Inner;
1497 fn from_repr(inner: Self::Inner) -> Self;
1498}
1499
1500pub trait Sanitizer<T> {
1511 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1512
1513 fn sanitize_with_context(
1514 &self,
1515 value: &mut T,
1516 ctx: &mut dyn VisitorContext,
1517 ) -> Result<(), String> {
1518 let _ = ctx;
1519
1520 self.sanitize(value)
1521 }
1522}
1523
1524pub trait Validator<T: ?Sized> {
1531 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1532}