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::{InputValue, Value, ValueEnum},
19 visitor::VisitorContext,
20};
21use std::collections::{BTreeMap, BTreeSet};
22
23pub use numeric_value::*;
24pub use visitor::*;
25
26pub use ic_memory::stable_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 const COMMIT_STABLE_KEY: &'static str;
77}
78
79pub trait StoreKind: Kind {
85 type Canister: CanisterKind;
86}
87
88pub trait EntityKey {
110 type Key: Copy
111 + Debug
112 + Eq
113 + Ord
114 + KeyValueCodec
115 + PrimaryKeyCodec
116 + PrimaryKeyDecode
117 + EntityKeyBytes
118 + 'static;
119}
120
121pub trait EntityKeyBytes {
126 const BYTE_LEN: usize;
128
129 fn write_bytes(&self, out: &mut [u8]);
131}
132
133macro_rules! impl_entity_key_bytes_numeric {
134 ($($ty:ty),* $(,)?) => {
135 $(
136 impl EntityKeyBytes for $ty {
137 const BYTE_LEN: usize = ::core::mem::size_of::<Self>();
138
139 fn write_bytes(&self, out: &mut [u8]) {
140 assert_eq!(out.len(), Self::BYTE_LEN);
141 out.copy_from_slice(&self.to_be_bytes());
142 }
143 }
144 )*
145 };
146}
147
148impl_entity_key_bytes_numeric!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128);
149
150impl EntityKeyBytes for () {
151 const BYTE_LEN: usize = 0;
152
153 fn write_bytes(&self, out: &mut [u8]) {
154 assert_eq!(out.len(), Self::BYTE_LEN);
155 }
156}
157
158pub trait ScalarRelationTargetKey {}
166
167macro_rules! impl_scalar_relation_target_key {
168 ($($ty:ty),* $(,)?) => {
169 $(
170 impl ScalarRelationTargetKey for $ty {}
171 )*
172 };
173}
174
175impl_scalar_relation_target_key!(
176 i8,
177 i16,
178 i32,
179 i64,
180 i128,
181 u8,
182 u16,
183 u32,
184 u64,
185 u128,
186 crate::types::Account,
187 crate::types::Principal,
188 crate::types::Subaccount,
189 crate::types::Timestamp,
190 crate::types::Ulid,
191 crate::types::Unit,
192 (),
193);
194
195pub trait ScalarRelationTargetKeyMatchesDeclaredPrimitive<Declared> {}
204
205impl<T> ScalarRelationTargetKeyMatchesDeclaredPrimitive<T> for T where T: ScalarRelationTargetKey {}
206
207pub trait KeyValueCodec {
217 fn to_key_value(&self) -> Value;
218
219 #[must_use]
220 fn from_key_value(value: &Value) -> Option<Self>
221 where
222 Self: Sized;
223}
224
225#[derive(Debug)]
234pub enum PrimaryKeyEncodeError {
235 UnsupportedComponentKind { kind: &'static str },
236
237 TooFewComponents { count: usize, min: usize },
238
239 TooManyComponents { count: usize, max: usize },
240
241 UnitComponent { index: usize },
242}
243
244impl From<CompositePrimaryKeyValueError> for PrimaryKeyEncodeError {
245 fn from(err: CompositePrimaryKeyValueError) -> Self {
246 match err {
247 CompositePrimaryKeyValueError::TooFewComponents { count, min } => {
248 Self::TooFewComponents { count, min }
249 }
250 CompositePrimaryKeyValueError::TooManyComponents { count, max } => {
251 Self::TooManyComponents { count, max }
252 }
253 CompositePrimaryKeyValueError::UnitComponent { index } => Self::UnitComponent { index },
254 }
255 }
256}
257
258impl From<PrimaryKeyEncodeError> for InternalError {
259 fn from(_err: PrimaryKeyEncodeError) -> Self {
260 Self::serialize_unsupported()
261 }
262}
263
264pub trait PrimaryKeyCodec {
273 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError>;
274}
275
276pub trait PrimaryKeyDecode: Sized {
286 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError>;
287}
288
289fn primary_key_variant_decode_failed(
290 _type_name: &'static str,
291 _key: &PrimaryKeyValue,
292 _expected: &'static str,
293) -> InternalError {
294 InternalError::store_corruption()
295}
296
297fn primary_key_range_decode_failed(
298 _type_name: &'static str,
299 _key: &PrimaryKeyValue,
300) -> InternalError {
301 InternalError::store_corruption()
302}
303
304macro_rules! impl_primary_key_codec_signed {
305 ($($ty:ty),* $(,)?) => {
306 $(
307 impl PrimaryKeyCodec for $ty {
308 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
309 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(i64::from(*self))))
310 }
311 }
312 )*
313 };
314}
315
316macro_rules! impl_primary_key_codec_unsigned {
317 ($($ty:ty),* $(,)?) => {
318 $(
319 impl PrimaryKeyCodec for $ty {
320 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
321 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(u64::from(*self))))
322 }
323 }
324 )*
325 };
326}
327
328impl<T> KeyValueCodec for T
329where
330 T: RuntimeValueDecode + RuntimeValueEncode,
331{
332 fn to_key_value(&self) -> Value {
333 self.to_value()
334 }
335
336 fn from_key_value(value: &Value) -> Option<Self> {
337 Self::from_value(value)
338 }
339}
340
341impl_primary_key_codec_signed!(i8, i16, i32, i64);
342impl_primary_key_codec_unsigned!(u8, u16, u32, u64);
343
344impl PrimaryKeyCodec for i128 {
345 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
346 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int128(*self)))
347 }
348}
349
350impl PrimaryKeyCodec for u128 {
351 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
352 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat128(*self)))
353 }
354}
355
356macro_rules! impl_primary_key_decode_signed {
357 ($($ty:ty),* $(,)?) => {
358 $(
359 impl PrimaryKeyDecode for $ty {
360 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
361 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(value)) = *key else {
362 return Err(primary_key_variant_decode_failed(
363 ::std::any::type_name::<Self>(),
364 key,
365 "PrimaryKeyComponent::Int64",
366 ));
367 };
368
369 Self::try_from(value).map_err(|_| {
370 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
371 })
372 }
373 }
374 )*
375 };
376}
377
378macro_rules! impl_primary_key_decode_unsigned {
379 ($($ty:ty),* $(,)?) => {
380 $(
381 impl PrimaryKeyDecode for $ty {
382 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
383 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(value)) = *key else {
384 return Err(primary_key_variant_decode_failed(
385 ::std::any::type_name::<Self>(),
386 key,
387 "PrimaryKeyComponent::Nat64",
388 ));
389 };
390
391 Self::try_from(value).map_err(|_| {
392 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
393 })
394 }
395 }
396 )*
397 };
398}
399
400impl_primary_key_decode_signed!(i8, i16, i32, i64);
401impl_primary_key_decode_unsigned!(u8, u16, u32, u64);
402
403impl PrimaryKeyDecode for i128 {
404 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
405 match *key {
406 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int128(value)) => Ok(value),
407 _ => Err(primary_key_variant_decode_failed(
408 ::std::any::type_name::<Self>(),
409 key,
410 "PrimaryKeyComponent::Int128",
411 )),
412 }
413 }
414}
415
416impl PrimaryKeyDecode for u128 {
417 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
418 match *key {
419 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat128(value)) => Ok(value),
420 _ => Err(primary_key_variant_decode_failed(
421 ::std::any::type_name::<Self>(),
422 key,
423 "PrimaryKeyComponent::Nat128",
424 )),
425 }
426 }
427}
428
429impl PrimaryKeyCodec for crate::types::Principal {
430 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
431 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(
432 *self,
433 )))
434 }
435}
436
437impl PrimaryKeyDecode for crate::types::Principal {
438 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
439 match *key {
440 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(value)) => Ok(value),
441 _ => Err(primary_key_variant_decode_failed(
442 ::std::any::type_name::<Self>(),
443 key,
444 "PrimaryKeyComponent::Principal",
445 )),
446 }
447 }
448}
449
450impl PrimaryKeyCodec for crate::types::Subaccount {
451 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
452 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(
453 *self,
454 )))
455 }
456}
457
458impl PrimaryKeyDecode for crate::types::Subaccount {
459 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
460 match *key {
461 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(value)) => Ok(value),
462 _ => Err(primary_key_variant_decode_failed(
463 ::std::any::type_name::<Self>(),
464 key,
465 "PrimaryKeyComponent::Subaccount",
466 )),
467 }
468 }
469}
470
471impl PrimaryKeyCodec for crate::types::Account {
472 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
473 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(*self)))
474 }
475}
476
477impl PrimaryKeyDecode for crate::types::Account {
478 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
479 match *key {
480 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(value)) => Ok(value),
481 _ => Err(primary_key_variant_decode_failed(
482 ::std::any::type_name::<Self>(),
483 key,
484 "PrimaryKeyComponent::Account",
485 )),
486 }
487 }
488}
489
490impl PrimaryKeyCodec for crate::types::Timestamp {
491 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
492 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(
493 *self,
494 )))
495 }
496}
497
498impl PrimaryKeyDecode for crate::types::Timestamp {
499 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
500 match *key {
501 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(value)) => Ok(value),
502 _ => Err(primary_key_variant_decode_failed(
503 ::std::any::type_name::<Self>(),
504 key,
505 "PrimaryKeyComponent::Timestamp",
506 )),
507 }
508 }
509}
510
511impl PrimaryKeyCodec for crate::types::Ulid {
512 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
513 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(*self)))
514 }
515}
516
517impl PrimaryKeyDecode for crate::types::Ulid {
518 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
519 match *key {
520 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(value)) => Ok(value),
521 _ => Err(primary_key_variant_decode_failed(
522 ::std::any::type_name::<Self>(),
523 key,
524 "PrimaryKeyComponent::Ulid",
525 )),
526 }
527 }
528}
529
530impl PrimaryKeyCodec for () {
531 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
532 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit))
533 }
534}
535
536impl PrimaryKeyDecode for () {
537 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
538 match *key {
539 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit) => Ok(()),
540 _ => Err(primary_key_variant_decode_failed(
541 ::std::any::type_name::<Self>(),
542 key,
543 "PrimaryKeyComponent::Unit",
544 )),
545 }
546 }
547}
548
549pub trait RuntimeValueEncode {
561 fn to_value(&self) -> Value;
562}
563
564pub trait RuntimeValueDecode {
575 #[must_use]
576 fn from_value(value: &Value) -> Option<Self>
577 where
578 Self: Sized;
579
580 #[doc(hidden)]
583 fn from_value_with_enum_context(
584 value: &Value,
585 _context: &dyn RuntimeEnumContext,
586 ) -> Option<Self>
587 where
588 Self: Sized,
589 {
590 Self::from_value(value)
591 }
592}
593
594#[doc(hidden)]
596pub struct RuntimeEnumSelection<'a> {
597 pub path: &'a str,
598 pub variant: &'a str,
599 pub payload: Option<&'a Value>,
600}
601
602#[doc(hidden)]
604pub trait RuntimeEnumContext {
605 fn resolve_enum<'a>(&'a self, value: &'a ValueEnum) -> Option<RuntimeEnumSelection<'a>>;
606}
607
608pub fn runtime_value_to_value<T>(value: &T) -> Value
617where
618 T: ?Sized + RuntimeValueEncode,
619{
620 value.to_value()
621}
622
623#[must_use]
632pub fn runtime_value_from_value<T>(value: &Value) -> Option<T>
633where
634 T: RuntimeValueDecode,
635{
636 T::from_value(value)
637}
638
639#[doc(hidden)]
641pub fn runtime_value_from_value_with_enum_context<T>(
642 value: &Value,
643 context: &dyn RuntimeEnumContext,
644) -> Option<T>
645where
646 T: RuntimeValueDecode,
647{
648 T::from_value_with_enum_context(value, context)
649}
650
651#[doc(hidden)]
653#[must_use]
654pub fn runtime_value_from_value_with_optional_enum_context<T>(
655 value: &Value,
656 context: Option<&dyn RuntimeEnumContext>,
657) -> Option<T>
658where
659 T: RuntimeValueDecode,
660{
661 match context {
662 Some(context) => T::from_value_with_enum_context(value, context),
663 None => T::from_value(value),
664 }
665}
666
667pub trait PersistedByKindCodec: Sized {
677 fn encode_persisted_slot_payload_by_kind(
679 &self,
680 kind: FieldKind,
681 field_name: &'static str,
682 ) -> Result<Vec<u8>, InternalError>;
683
684 fn decode_persisted_option_slot_payload_by_kind(
688 bytes: &[u8],
689 kind: FieldKind,
690 field_name: &'static str,
691 ) -> Result<Option<Self>, InternalError>;
692}
693
694pub trait PersistedStructuredFieldCodec {
706 fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
708
709 fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
711 where
712 Self: Sized;
713}
714
715pub trait EntitySchema: EntityKey {
726 const NAME: &'static str;
727 const MODEL: &'static EntityModel;
728}
729
730pub trait EntityPlacement {
744 type Store: StoreKind;
745 type Canister: CanisterKind;
746}
747
748pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
758 const ENTITY_TAG: EntityTag;
759}
760
761pub trait EntityValue: EntityKey + AuthoredFieldProjection + FieldProjection + Sized {
779 fn id(&self) -> Id<Self>;
780}
781
782pub struct EntityCreateMaterialization<E> {
791 entity: E,
792 authored_slots: Vec<usize>,
793}
794
795impl<E> EntityCreateMaterialization<E> {
796 #[must_use]
798 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
799 Self {
800 entity,
801 authored_slots,
802 }
803 }
804
805 #[must_use]
807 pub fn into_entity(self) -> E {
808 self.entity
809 }
810
811 #[must_use]
813 pub const fn authored_slots(&self) -> &[usize] {
814 self.authored_slots.as_slice()
815 }
816}
817
818pub trait EntityCreateInput: Sized {
827 type Entity: EntityValue;
828
829 fn materialize_create(self)
831 -> Result<EntityCreateMaterialization<Self::Entity>, InternalError>;
832}
833
834pub trait EntityCreateType: EntityValue {
844 type Create: EntityCreateInput<Entity = Self>;
845}
846
847pub trait SingletonEntity: EntityValue {}
849
850pub trait TypeKind:
868 Kind + Clone + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
869{
870}
871
872impl<T> TypeKind for T where
873 T: Kind + Clone + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
874{
875}
876
877pub trait FieldTypeMeta {
886 const KIND: FieldKind;
888
889 const STORAGE_DECODE: FieldStorageDecode;
891
892 const NESTED_FIELDS: &'static [FieldModel] = &[];
894}
895
896impl<T> FieldTypeMeta for Option<T>
897where
898 T: FieldTypeMeta,
899{
900 const KIND: FieldKind = T::KIND;
901 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
902 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
903}
904
905impl<T> FieldTypeMeta for Box<T>
906where
907 T: FieldTypeMeta,
908{
909 const KIND: FieldKind = T::KIND;
910 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
911 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
912}
913
914impl<T> FieldTypeMeta for Vec<T>
918where
919 T: FieldTypeMeta,
920{
921 const KIND: FieldKind = FieldKind::List(&T::KIND);
922 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
923}
924
925impl<T> FieldTypeMeta for BTreeSet<T>
926where
927 T: FieldTypeMeta,
928{
929 const KIND: FieldKind = FieldKind::Set(&T::KIND);
930 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
931}
932
933impl<K, V> FieldTypeMeta for BTreeMap<K, V>
934where
935 K: FieldTypeMeta,
936 V: FieldTypeMeta,
937{
938 const KIND: FieldKind = FieldKind::Map {
939 key: &K::KIND,
940 value: &V::KIND,
941 };
942 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
943}
944
945pub trait Collection {
958 type Item;
959
960 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
962 where
963 Self: 'a;
964
965 fn iter(&self) -> Self::Iter<'_>;
967
968 fn len(&self) -> usize;
970
971 fn is_empty(&self) -> bool {
973 self.len() == 0
974 }
975}
976
977pub trait MapCollection {
986 type Key;
987 type Value;
988
989 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
991 where
992 Self: 'a;
993
994 fn iter(&self) -> Self::Iter<'_>;
996
997 fn len(&self) -> usize;
999
1000 fn is_empty(&self) -> bool {
1002 self.len() == 0
1003 }
1004}
1005
1006impl<T> Collection for Vec<T> {
1007 type Item = T;
1008 type Iter<'a>
1009 = std::slice::Iter<'a, T>
1010 where
1011 Self: 'a;
1012
1013 fn iter(&self) -> Self::Iter<'_> {
1014 self.as_slice().iter()
1015 }
1016
1017 fn len(&self) -> usize {
1018 self.as_slice().len()
1019 }
1020}
1021
1022impl<T> Collection for BTreeSet<T> {
1023 type Item = T;
1024 type Iter<'a>
1025 = std::collections::btree_set::Iter<'a, T>
1026 where
1027 Self: 'a;
1028
1029 fn iter(&self) -> Self::Iter<'_> {
1030 self.iter()
1031 }
1032
1033 fn len(&self) -> usize {
1034 self.len()
1035 }
1036}
1037
1038impl<K, V> MapCollection for BTreeMap<K, V> {
1039 type Key = K;
1040 type Value = V;
1041 type Iter<'a>
1042 = std::collections::btree_map::Iter<'a, K, V>
1043 where
1044 Self: 'a;
1045
1046 fn iter(&self) -> Self::Iter<'_> {
1047 self.iter()
1048 }
1049
1050 fn len(&self) -> usize {
1051 self.len()
1052 }
1053}
1054
1055pub trait AuthoredFieldProjection {
1057 fn get_input_value_by_index(&self, index: usize) -> Option<InputValue>;
1059}
1060
1061pub trait FieldProjection {
1062 fn get_value_by_index(&self, index: usize) -> Option<Value>;
1064}
1065
1066#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1074pub enum RuntimeValueKind {
1075 Atomic,
1077
1078 Structured {
1081 queryable: bool,
1083 },
1084}
1085
1086impl RuntimeValueKind {
1087 #[must_use]
1088 pub const fn is_queryable(self) -> bool {
1089 match self {
1090 Self::Atomic => true,
1091 Self::Structured { queryable } => queryable,
1092 }
1093 }
1094}
1095
1096pub trait RuntimeValueMeta {
1105 fn kind() -> RuntimeValueKind
1106 where
1107 Self: Sized;
1108}
1109
1110pub fn runtime_value_collection_to_value<C>(collection: &C) -> Value
1119where
1120 C: Collection,
1121 C::Item: RuntimeValueEncode,
1122{
1123 Value::List(
1124 collection
1125 .iter()
1126 .map(RuntimeValueEncode::to_value)
1127 .collect(),
1128 )
1129}
1130
1131#[must_use]
1140pub fn runtime_value_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
1141where
1142 T: RuntimeValueDecode,
1143{
1144 let Value::List(values) = value else {
1145 return None;
1146 };
1147
1148 let mut out = Vec::with_capacity(values.len());
1149 for value in values {
1150 out.push(T::from_value(value)?);
1151 }
1152
1153 Some(out)
1154}
1155
1156#[must_use]
1165pub fn runtime_value_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
1166where
1167 T: Ord + RuntimeValueDecode,
1168{
1169 let Value::List(values) = value else {
1170 return None;
1171 };
1172
1173 let mut out = BTreeSet::new();
1174 for value in values {
1175 let item = T::from_value(value)?;
1176 if !out.insert(item) {
1177 return None;
1178 }
1179 }
1180
1181 Some(out)
1182}
1183
1184pub fn runtime_value_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
1194where
1195 M: MapCollection,
1196 M::Key: RuntimeValueEncode,
1197 M::Value: RuntimeValueEncode,
1198{
1199 let mut entries: Vec<(Value, Value)> = map
1200 .iter()
1201 .map(|(key, value)| {
1202 (
1203 RuntimeValueEncode::to_value(key),
1204 RuntimeValueEncode::to_value(value),
1205 )
1206 })
1207 .collect();
1208
1209 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
1210 debug_assert!(false, "invalid map field value for {path}: {err}");
1211 return Value::Map(entries);
1212 }
1213
1214 Value::sort_map_entries_in_place(entries.as_mut_slice());
1215
1216 for i in 1..entries.len() {
1217 let (left_key, _) = &entries[i - 1];
1218 let (right_key, _) = &entries[i];
1219 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
1220 debug_assert!(
1221 false,
1222 "duplicate map key in {path} after value-surface canonicalization",
1223 );
1224 break;
1225 }
1226 }
1227
1228 Value::Map(entries)
1229}
1230
1231#[must_use]
1240pub fn runtime_value_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
1241where
1242 K: Ord + RuntimeValueDecode,
1243 V: RuntimeValueDecode,
1244{
1245 let Value::Map(entries) = value else {
1246 return None;
1247 };
1248
1249 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
1250 if normalized.as_slice() != entries.as_slice() {
1251 return None;
1252 }
1253
1254 let mut map = BTreeMap::new();
1255 for (entry_key, entry_value) in normalized {
1256 let key = K::from_value(&entry_key)?;
1257 let value = V::from_value(&entry_value)?;
1258 map.insert(key, value);
1259 }
1260
1261 Some(map)
1262}
1263
1264#[must_use]
1273pub fn runtime_value_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
1274where
1275 I: Into<T>,
1276{
1277 entries.into_iter().map(Into::into).collect()
1278}
1279
1280#[must_use]
1289pub fn runtime_value_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
1290where
1291 I: Into<T>,
1292 T: Ord,
1293{
1294 entries.into_iter().map(Into::into).collect()
1295}
1296
1297#[must_use]
1306pub fn runtime_value_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
1307where
1308 IK: Into<K>,
1309 IV: Into<V>,
1310 K: Ord,
1311{
1312 entries
1313 .into_iter()
1314 .map(|(key, value)| (key.into(), value.into()))
1315 .collect()
1316}
1317
1318#[must_use]
1327pub fn runtime_value_into<T, U>(value: U) -> T
1328where
1329 U: Into<T>,
1330{
1331 value.into()
1332}
1333
1334impl RuntimeValueMeta for &str {
1335 fn kind() -> RuntimeValueKind {
1336 RuntimeValueKind::Atomic
1337 }
1338}
1339
1340impl RuntimeValueEncode for &str {
1341 fn to_value(&self) -> Value {
1342 Value::Text((*self).to_string())
1343 }
1344}
1345
1346impl RuntimeValueDecode for &str {
1347 fn from_value(_value: &Value) -> Option<Self> {
1348 None
1349 }
1350}
1351
1352impl RuntimeValueMeta for String {
1353 fn kind() -> RuntimeValueKind {
1354 RuntimeValueKind::Atomic
1355 }
1356}
1357
1358impl RuntimeValueEncode for String {
1359 fn to_value(&self) -> Value {
1360 Value::Text(self.clone())
1361 }
1362}
1363
1364impl RuntimeValueDecode for String {
1365 fn from_value(value: &Value) -> Option<Self> {
1366 match value {
1367 Value::Text(v) => Some(v.clone()),
1368 _ => None,
1369 }
1370 }
1371}
1372
1373impl<T: RuntimeValueMeta> RuntimeValueMeta for Option<T> {
1374 fn kind() -> RuntimeValueKind {
1375 T::kind()
1376 }
1377}
1378
1379impl<T: RuntimeValueEncode> RuntimeValueEncode for Option<T> {
1380 fn to_value(&self) -> Value {
1381 match self {
1382 Some(v) => v.to_value(),
1383 None => Value::Null,
1384 }
1385 }
1386}
1387
1388impl<T: RuntimeValueDecode> RuntimeValueDecode for Option<T> {
1389 fn from_value(value: &Value) -> Option<Self> {
1390 if matches!(value, Value::Null) {
1391 return Some(None);
1392 }
1393
1394 T::from_value(value).map(Some)
1395 }
1396
1397 fn from_value_with_enum_context(
1398 value: &Value,
1399 context: &dyn RuntimeEnumContext,
1400 ) -> Option<Self> {
1401 if matches!(value, Value::Null) {
1402 return Some(None);
1403 }
1404
1405 T::from_value_with_enum_context(value, context).map(Some)
1406 }
1407}
1408
1409impl<T: RuntimeValueMeta> RuntimeValueMeta for Box<T> {
1410 fn kind() -> RuntimeValueKind {
1411 T::kind()
1412 }
1413}
1414
1415impl<T: RuntimeValueEncode> RuntimeValueEncode for Box<T> {
1416 fn to_value(&self) -> Value {
1417 (**self).to_value()
1418 }
1419}
1420
1421impl<T: RuntimeValueDecode> RuntimeValueDecode for Box<T> {
1422 fn from_value(value: &Value) -> Option<Self> {
1423 T::from_value(value).map(Self::new)
1424 }
1425
1426 fn from_value_with_enum_context(
1427 value: &Value,
1428 context: &dyn RuntimeEnumContext,
1429 ) -> Option<Self> {
1430 T::from_value_with_enum_context(value, context).map(Self::new)
1431 }
1432}
1433
1434impl<T> RuntimeValueMeta for Vec<T> {
1435 fn kind() -> RuntimeValueKind {
1436 RuntimeValueKind::Structured { queryable: true }
1437 }
1438}
1439
1440impl<T: RuntimeValueEncode> RuntimeValueEncode for Vec<T> {
1441 fn to_value(&self) -> Value {
1442 runtime_value_collection_to_value(self)
1443 }
1444}
1445
1446impl<T: RuntimeValueDecode> RuntimeValueDecode for Vec<T> {
1447 fn from_value(value: &Value) -> Option<Self> {
1448 runtime_value_vec_from_value(value)
1449 }
1450
1451 fn from_value_with_enum_context(
1452 value: &Value,
1453 context: &dyn RuntimeEnumContext,
1454 ) -> Option<Self> {
1455 let Value::List(values) = value else {
1456 return None;
1457 };
1458 values
1459 .iter()
1460 .map(|value| T::from_value_with_enum_context(value, context))
1461 .collect()
1462 }
1463}
1464
1465impl<T> RuntimeValueMeta for BTreeSet<T>
1466where
1467 T: Ord,
1468{
1469 fn kind() -> RuntimeValueKind {
1470 RuntimeValueKind::Structured { queryable: true }
1471 }
1472}
1473
1474impl<T> RuntimeValueEncode for BTreeSet<T>
1475where
1476 T: Ord + RuntimeValueEncode,
1477{
1478 fn to_value(&self) -> Value {
1479 runtime_value_collection_to_value(self)
1480 }
1481}
1482
1483impl<T> RuntimeValueDecode for BTreeSet<T>
1484where
1485 T: Ord + RuntimeValueDecode,
1486{
1487 fn from_value(value: &Value) -> Option<Self> {
1488 runtime_value_btree_set_from_value(value)
1489 }
1490
1491 fn from_value_with_enum_context(
1492 value: &Value,
1493 context: &dyn RuntimeEnumContext,
1494 ) -> Option<Self> {
1495 let Value::List(values) = value else {
1496 return None;
1497 };
1498 values
1499 .iter()
1500 .map(|value| T::from_value_with_enum_context(value, context))
1501 .collect()
1502 }
1503}
1504
1505impl<K, V> RuntimeValueMeta for BTreeMap<K, V>
1506where
1507 K: Ord,
1508{
1509 fn kind() -> RuntimeValueKind {
1510 RuntimeValueKind::Structured { queryable: true }
1511 }
1512}
1513
1514impl<K, V> RuntimeValueEncode for BTreeMap<K, V>
1515where
1516 K: Ord + RuntimeValueEncode,
1517 V: RuntimeValueEncode,
1518{
1519 fn to_value(&self) -> Value {
1520 runtime_value_map_collection_to_value(self, std::any::type_name::<Self>())
1521 }
1522}
1523
1524impl<K, V> RuntimeValueDecode for BTreeMap<K, V>
1525where
1526 K: Ord + RuntimeValueDecode,
1527 V: RuntimeValueDecode,
1528{
1529 fn from_value(value: &Value) -> Option<Self> {
1530 runtime_value_btree_map_from_value(value)
1531 }
1532
1533 fn from_value_with_enum_context(
1534 value: &Value,
1535 context: &dyn RuntimeEnumContext,
1536 ) -> Option<Self> {
1537 let Value::Map(entries) = value else {
1538 return None;
1539 };
1540 entries
1541 .iter()
1542 .map(|(key, value)| {
1543 Some((
1544 K::from_value_with_enum_context(key, context)?,
1545 V::from_value_with_enum_context(value, context)?,
1546 ))
1547 })
1548 .collect()
1549 }
1550}
1551
1552#[macro_export]
1554macro_rules! impl_runtime_value {
1555 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
1556 $(
1557 impl RuntimeValueMeta for $type {
1558 fn kind() -> RuntimeValueKind {
1559 RuntimeValueKind::Atomic
1560 }
1561 }
1562
1563 impl RuntimeValueEncode for $type {
1564 fn to_value(&self) -> Value {
1565 Value::$variant((*self).into())
1566 }
1567 }
1568
1569 impl RuntimeValueDecode for $type {
1570 fn from_value(value: &Value) -> Option<Self> {
1571 match value {
1572 Value::$variant(v) => (*v).try_into().ok(),
1573 _ => None,
1574 }
1575 }
1576 }
1577 )*
1578 };
1579}
1580
1581impl_runtime_value!(
1582 i8 => Int64,
1583 i16 => Int64,
1584 i32 => Int64,
1585 i64 => Int64,
1586 i128 => Int128,
1587 u8 => Nat64,
1588 u16 => Nat64,
1589 u32 => Nat64,
1590 u64 => Nat64,
1591 u128 => Nat128,
1592 bool => Bool,
1593);
1594
1595pub trait Inner<T> {
1606 fn inner(&self) -> &T;
1607 fn into_inner(self) -> T;
1608}
1609
1610pub trait Repr {
1617 type Inner;
1618
1619 fn repr(&self) -> Self::Inner;
1620 fn from_repr(inner: Self::Inner) -> Self;
1621}
1622
1623pub trait Sanitizer<T> {
1634 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1635
1636 fn sanitize_with_context(
1637 &self,
1638 value: &mut T,
1639 ctx: &mut dyn VisitorContext,
1640 ) -> Result<(), String> {
1641 let _ = ctx;
1642
1643 self.sanitize(value)
1644 }
1645}
1646
1647pub trait Validator<T: ?Sized> {
1654 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1655}