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, i128, u8, u16, u32, u64, u128);
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 ScalarRelationTargetKey {}
167
168macro_rules! impl_scalar_relation_target_key {
169 ($($ty:ty),* $(,)?) => {
170 $(
171 impl ScalarRelationTargetKey for $ty {}
172 )*
173 };
174}
175
176impl_scalar_relation_target_key!(
177 i8,
178 i16,
179 i32,
180 i64,
181 i128,
182 u8,
183 u16,
184 u32,
185 u64,
186 u128,
187 crate::types::Account,
188 crate::types::Principal,
189 crate::types::Subaccount,
190 crate::types::Timestamp,
191 crate::types::Ulid,
192 crate::types::Unit,
193 (),
194);
195
196pub trait ScalarRelationTargetKeyMatchesDeclaredPrimitive<Declared> {}
205
206impl<T> ScalarRelationTargetKeyMatchesDeclaredPrimitive<T> for T where T: ScalarRelationTargetKey {}
207
208pub trait KeyValueCodec {
218 fn to_key_value(&self) -> Value;
219
220 #[must_use]
221 fn from_key_value(value: &Value) -> Option<Self>
222 where
223 Self: Sized;
224}
225
226#[derive(Debug, ThisError)]
235pub enum PrimaryKeyEncodeError {
236 #[error("primary-key component kind '{kind}' is not admitted")]
237 UnsupportedComponentKind { kind: &'static str },
238
239 #[error("composite primary key has too few components: {count} (minimum {min})")]
240 TooFewComponents { count: usize, min: usize },
241
242 #[error("composite primary key has too many components: {count} (limit {max})")]
243 TooManyComponents { count: usize, max: usize },
244
245 #[error("unit is not admitted as composite primary-key component {index}")]
246 UnitComponent { index: usize },
247}
248
249impl From<CompositePrimaryKeyValueError> for PrimaryKeyEncodeError {
250 fn from(err: CompositePrimaryKeyValueError) -> Self {
251 match err {
252 CompositePrimaryKeyValueError::TooFewComponents { count, min } => {
253 Self::TooFewComponents { count, min }
254 }
255 CompositePrimaryKeyValueError::TooManyComponents { count, max } => {
256 Self::TooManyComponents { count, max }
257 }
258 CompositePrimaryKeyValueError::UnitComponent { index } => Self::UnitComponent { index },
259 }
260 }
261}
262
263impl From<PrimaryKeyEncodeError> for InternalError {
264 fn from(err: PrimaryKeyEncodeError) -> Self {
265 Self::serialize_unsupported(err.to_string())
266 }
267}
268
269pub trait PrimaryKeyCodec {
278 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError>;
279}
280
281pub trait PrimaryKeyDecode: Sized {
291 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError>;
292}
293
294fn primary_key_variant_decode_failed(
295 type_name: &'static str,
296 key: &PrimaryKeyValue,
297 expected: &'static str,
298) -> InternalError {
299 InternalError::store_corruption(format!(
300 "primary key decode failed for `{type_name}`: expected {expected}, found {key:?}",
301 ))
302}
303
304fn primary_key_range_decode_failed(
305 type_name: &'static str,
306 key: &PrimaryKeyValue,
307) -> InternalError {
308 InternalError::store_corruption(format!(
309 "primary key decode failed for `{type_name}`: value out of range for {key:?}",
310 ))
311}
312
313macro_rules! impl_primary_key_codec_signed {
314 ($($ty:ty),* $(,)?) => {
315 $(
316 impl PrimaryKeyCodec for $ty {
317 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
318 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(i64::from(*self))))
319 }
320 }
321 )*
322 };
323}
324
325macro_rules! impl_primary_key_codec_unsigned {
326 ($($ty:ty),* $(,)?) => {
327 $(
328 impl PrimaryKeyCodec for $ty {
329 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
330 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(u64::from(*self))))
331 }
332 }
333 )*
334 };
335}
336
337impl<T> KeyValueCodec for T
338where
339 T: RuntimeValueDecode + RuntimeValueEncode,
340{
341 fn to_key_value(&self) -> Value {
342 self.to_value()
343 }
344
345 fn from_key_value(value: &Value) -> Option<Self> {
346 Self::from_value(value)
347 }
348}
349
350impl_primary_key_codec_signed!(i8, i16, i32, i64);
351impl_primary_key_codec_unsigned!(u8, u16, u32, u64);
352
353impl PrimaryKeyCodec for i128 {
354 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
355 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int128(*self)))
356 }
357}
358
359impl PrimaryKeyCodec for u128 {
360 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
361 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat128(*self)))
362 }
363}
364
365macro_rules! impl_primary_key_decode_signed {
366 ($($ty:ty),* $(,)?) => {
367 $(
368 impl PrimaryKeyDecode for $ty {
369 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
370 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int64(value)) = *key else {
371 return Err(primary_key_variant_decode_failed(
372 ::std::any::type_name::<Self>(),
373 key,
374 "PrimaryKeyComponent::Int64",
375 ));
376 };
377
378 Self::try_from(value).map_err(|_| {
379 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
380 })
381 }
382 }
383 )*
384 };
385}
386
387macro_rules! impl_primary_key_decode_unsigned {
388 ($($ty:ty),* $(,)?) => {
389 $(
390 impl PrimaryKeyDecode for $ty {
391 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
392 let PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat64(value)) = *key else {
393 return Err(primary_key_variant_decode_failed(
394 ::std::any::type_name::<Self>(),
395 key,
396 "PrimaryKeyComponent::Nat64",
397 ));
398 };
399
400 Self::try_from(value).map_err(|_| {
401 primary_key_range_decode_failed(::std::any::type_name::<Self>(), key)
402 })
403 }
404 }
405 )*
406 };
407}
408
409impl_primary_key_decode_signed!(i8, i16, i32, i64);
410impl_primary_key_decode_unsigned!(u8, u16, u32, u64);
411
412impl PrimaryKeyDecode for i128 {
413 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
414 match *key {
415 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Int128(value)) => Ok(value),
416 _ => Err(primary_key_variant_decode_failed(
417 ::std::any::type_name::<Self>(),
418 key,
419 "PrimaryKeyComponent::Int128",
420 )),
421 }
422 }
423}
424
425impl PrimaryKeyDecode for u128 {
426 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
427 match *key {
428 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Nat128(value)) => Ok(value),
429 _ => Err(primary_key_variant_decode_failed(
430 ::std::any::type_name::<Self>(),
431 key,
432 "PrimaryKeyComponent::Nat128",
433 )),
434 }
435 }
436}
437
438impl PrimaryKeyCodec for crate::types::Principal {
439 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
440 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(
441 *self,
442 )))
443 }
444}
445
446impl PrimaryKeyDecode for crate::types::Principal {
447 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
448 match *key {
449 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Principal(value)) => Ok(value),
450 _ => Err(primary_key_variant_decode_failed(
451 ::std::any::type_name::<Self>(),
452 key,
453 "PrimaryKeyComponent::Principal",
454 )),
455 }
456 }
457}
458
459impl PrimaryKeyCodec for crate::types::Subaccount {
460 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
461 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(
462 *self,
463 )))
464 }
465}
466
467impl PrimaryKeyDecode for crate::types::Subaccount {
468 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
469 match *key {
470 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Subaccount(value)) => Ok(value),
471 _ => Err(primary_key_variant_decode_failed(
472 ::std::any::type_name::<Self>(),
473 key,
474 "PrimaryKeyComponent::Subaccount",
475 )),
476 }
477 }
478}
479
480impl PrimaryKeyCodec for crate::types::Account {
481 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
482 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(*self)))
483 }
484}
485
486impl PrimaryKeyDecode for crate::types::Account {
487 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
488 match *key {
489 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Account(value)) => Ok(value),
490 _ => Err(primary_key_variant_decode_failed(
491 ::std::any::type_name::<Self>(),
492 key,
493 "PrimaryKeyComponent::Account",
494 )),
495 }
496 }
497}
498
499impl PrimaryKeyCodec for crate::types::Timestamp {
500 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
501 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(
502 *self,
503 )))
504 }
505}
506
507impl PrimaryKeyDecode for crate::types::Timestamp {
508 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
509 match *key {
510 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Timestamp(value)) => Ok(value),
511 _ => Err(primary_key_variant_decode_failed(
512 ::std::any::type_name::<Self>(),
513 key,
514 "PrimaryKeyComponent::Timestamp",
515 )),
516 }
517 }
518}
519
520impl PrimaryKeyCodec for crate::types::Ulid {
521 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
522 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(*self)))
523 }
524}
525
526impl PrimaryKeyDecode for crate::types::Ulid {
527 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
528 match *key {
529 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Ulid(value)) => Ok(value),
530 _ => Err(primary_key_variant_decode_failed(
531 ::std::any::type_name::<Self>(),
532 key,
533 "PrimaryKeyComponent::Ulid",
534 )),
535 }
536 }
537}
538
539impl PrimaryKeyCodec for () {
540 fn to_primary_key_value(&self) -> Result<PrimaryKeyValue, PrimaryKeyEncodeError> {
541 Ok(PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit))
542 }
543}
544
545impl PrimaryKeyDecode for () {
546 fn from_primary_key_value(key: &PrimaryKeyValue) -> Result<Self, InternalError> {
547 match *key {
548 PrimaryKeyValue::Scalar(PrimaryKeyComponent::Unit) => Ok(()),
549 _ => Err(primary_key_variant_decode_failed(
550 ::std::any::type_name::<Self>(),
551 key,
552 "PrimaryKeyComponent::Unit",
553 )),
554 }
555 }
556}
557
558pub trait RuntimeValueEncode {
570 fn to_value(&self) -> Value;
571}
572
573pub trait RuntimeValueDecode {
584 #[must_use]
585 fn from_value(value: &Value) -> Option<Self>
586 where
587 Self: Sized;
588}
589
590pub fn runtime_value_to_value<T>(value: &T) -> Value
599where
600 T: ?Sized + RuntimeValueEncode,
601{
602 value.to_value()
603}
604
605#[must_use]
614pub fn runtime_value_from_value<T>(value: &Value) -> Option<T>
615where
616 T: RuntimeValueDecode,
617{
618 T::from_value(value)
619}
620
621pub trait PersistedByKindCodec: Sized {
631 fn encode_persisted_slot_payload_by_kind(
633 &self,
634 kind: FieldKind,
635 field_name: &'static str,
636 ) -> Result<Vec<u8>, InternalError>;
637
638 fn decode_persisted_option_slot_payload_by_kind(
642 bytes: &[u8],
643 kind: FieldKind,
644 field_name: &'static str,
645 ) -> Result<Option<Self>, InternalError>;
646}
647
648pub trait PersistedStructuredFieldCodec {
660 fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError>;
662
663 fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError>
665 where
666 Self: Sized;
667}
668
669pub trait EntitySchema: EntityKey {
680 const NAME: &'static str;
681 const MODEL: &'static EntityModel;
682}
683
684pub trait EntityPlacement {
698 type Store: StoreKind;
699 type Canister: CanisterKind;
700}
701
702pub trait EntityKind: EntitySchema + EntityPlacement + Kind + TypeKind {
712 const ENTITY_TAG: EntityTag;
713}
714
715pub trait EntityValue: EntityKey + FieldProjection + Sized {
733 fn id(&self) -> Id<Self>;
734}
735
736pub struct EntityCreateMaterialization<E> {
745 entity: E,
746 authored_slots: Vec<usize>,
747}
748
749impl<E> EntityCreateMaterialization<E> {
750 #[must_use]
752 pub const fn new(entity: E, authored_slots: Vec<usize>) -> Self {
753 Self {
754 entity,
755 authored_slots,
756 }
757 }
758
759 #[must_use]
761 pub fn into_entity(self) -> E {
762 self.entity
763 }
764
765 #[must_use]
767 pub const fn authored_slots(&self) -> &[usize] {
768 self.authored_slots.as_slice()
769 }
770}
771
772pub trait EntityCreateInput: Sized {
781 type Entity: EntityValue;
782
783 fn materialize_create(self)
785 -> Result<EntityCreateMaterialization<Self::Entity>, InternalError>;
786}
787
788pub trait EntityCreateType: EntityValue {
798 type Create: EntityCreateInput<Entity = Self>;
799}
800
801pub trait SingletonEntity: EntityValue {}
803
804pub trait TypeKind:
822 Kind + Clone + DeserializeOwned + Sanitize + Validate + Visitable + PartialEq
823{
824}
825
826impl<T> TypeKind for T where
827 T: Kind + Clone + DeserializeOwned + PartialEq + Sanitize + Validate + Visitable
828{
829}
830
831pub trait FieldTypeMeta {
840 const KIND: FieldKind;
842
843 const STORAGE_DECODE: FieldStorageDecode;
845
846 const NESTED_FIELDS: &'static [FieldModel] = &[];
848}
849
850pub trait PersistedFieldMetaCodec: FieldTypeMeta + Sized {
861 fn encode_persisted_slot_payload_by_meta(
864 &self,
865 field_name: &'static str,
866 ) -> Result<Vec<u8>, InternalError>;
867
868 fn decode_persisted_slot_payload_by_meta(
871 bytes: &[u8],
872 field_name: &'static str,
873 ) -> Result<Self, InternalError>;
874
875 fn encode_persisted_option_slot_payload_by_meta(
878 value: &Option<Self>,
879 field_name: &'static str,
880 ) -> Result<Vec<u8>, InternalError>;
881
882 fn decode_persisted_option_slot_payload_by_meta(
885 bytes: &[u8],
886 field_name: &'static str,
887 ) -> Result<Option<Self>, InternalError>;
888}
889
890pub trait PersistedFieldSlotCodec: Sized {
900 fn encode_persisted_slot(&self, field_name: &'static str) -> Result<Vec<u8>, InternalError>;
903
904 fn decode_persisted_slot(bytes: &[u8], field_name: &'static str)
907 -> Result<Self, InternalError>;
908
909 fn encode_persisted_option_slot(
912 value: &Option<Self>,
913 field_name: &'static str,
914 ) -> Result<Vec<u8>, InternalError>;
915
916 fn decode_persisted_option_slot(
919 bytes: &[u8],
920 field_name: &'static str,
921 ) -> Result<Option<Self>, InternalError>;
922}
923
924impl<T> FieldTypeMeta for Option<T>
925where
926 T: FieldTypeMeta,
927{
928 const KIND: FieldKind = T::KIND;
929 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
930 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
931}
932
933impl<T> FieldTypeMeta for Box<T>
934where
935 T: FieldTypeMeta,
936{
937 const KIND: FieldKind = T::KIND;
938 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
939 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
940}
941
942impl<T> FieldTypeMeta for Vec<T>
946where
947 T: FieldTypeMeta,
948{
949 const KIND: FieldKind = FieldKind::List(&T::KIND);
950 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
951}
952
953impl<T> FieldTypeMeta for BTreeSet<T>
954where
955 T: FieldTypeMeta,
956{
957 const KIND: FieldKind = FieldKind::Set(&T::KIND);
958 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
959}
960
961impl<K, V> FieldTypeMeta for BTreeMap<K, V>
962where
963 K: FieldTypeMeta,
964 V: FieldTypeMeta,
965{
966 const KIND: FieldKind = FieldKind::Map {
967 key: &K::KIND,
968 value: &V::KIND,
969 };
970 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
971}
972
973pub trait Collection {
986 type Item;
987
988 type Iter<'a>: Iterator<Item = &'a Self::Item> + 'a
990 where
991 Self: 'a;
992
993 fn iter(&self) -> Self::Iter<'_>;
995
996 fn len(&self) -> usize;
998
999 fn is_empty(&self) -> bool {
1001 self.len() == 0
1002 }
1003}
1004
1005pub trait MapCollection {
1014 type Key;
1015 type Value;
1016
1017 type Iter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)> + 'a
1019 where
1020 Self: 'a;
1021
1022 fn iter(&self) -> Self::Iter<'_>;
1024
1025 fn len(&self) -> usize;
1027
1028 fn is_empty(&self) -> bool {
1030 self.len() == 0
1031 }
1032}
1033
1034impl<T> Collection for Vec<T> {
1035 type Item = T;
1036 type Iter<'a>
1037 = std::slice::Iter<'a, T>
1038 where
1039 Self: 'a;
1040
1041 fn iter(&self) -> Self::Iter<'_> {
1042 self.as_slice().iter()
1043 }
1044
1045 fn len(&self) -> usize {
1046 self.as_slice().len()
1047 }
1048}
1049
1050impl<T> Collection for BTreeSet<T> {
1051 type Item = T;
1052 type Iter<'a>
1053 = std::collections::btree_set::Iter<'a, T>
1054 where
1055 Self: 'a;
1056
1057 fn iter(&self) -> Self::Iter<'_> {
1058 self.iter()
1059 }
1060
1061 fn len(&self) -> usize {
1062 self.len()
1063 }
1064}
1065
1066impl<K, V> MapCollection for BTreeMap<K, V> {
1067 type Key = K;
1068 type Value = V;
1069 type Iter<'a>
1070 = std::collections::btree_map::Iter<'a, K, V>
1071 where
1072 Self: 'a;
1073
1074 fn iter(&self) -> Self::Iter<'_> {
1075 self.iter()
1076 }
1077
1078 fn len(&self) -> usize {
1079 self.len()
1080 }
1081}
1082
1083pub trait EnumValue {
1084 fn to_value_enum(&self) -> ValueEnum;
1085}
1086
1087pub trait FieldProjection {
1088 fn get_value_by_index(&self, index: usize) -> Option<Value>;
1090}
1091
1092#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1100pub enum RuntimeValueKind {
1101 Atomic,
1103
1104 Structured {
1107 queryable: bool,
1109 },
1110}
1111
1112impl RuntimeValueKind {
1113 #[must_use]
1114 pub const fn is_queryable(self) -> bool {
1115 match self {
1116 Self::Atomic => true,
1117 Self::Structured { queryable } => queryable,
1118 }
1119 }
1120}
1121
1122pub trait RuntimeValueMeta {
1131 fn kind() -> RuntimeValueKind
1132 where
1133 Self: Sized;
1134}
1135
1136pub fn runtime_value_collection_to_value<C>(collection: &C) -> Value
1145where
1146 C: Collection,
1147 C::Item: RuntimeValueEncode,
1148{
1149 Value::List(
1150 collection
1151 .iter()
1152 .map(RuntimeValueEncode::to_value)
1153 .collect(),
1154 )
1155}
1156
1157#[must_use]
1166pub fn runtime_value_vec_from_value<T>(value: &Value) -> Option<Vec<T>>
1167where
1168 T: RuntimeValueDecode,
1169{
1170 let Value::List(values) = value else {
1171 return None;
1172 };
1173
1174 let mut out = Vec::with_capacity(values.len());
1175 for value in values {
1176 out.push(T::from_value(value)?);
1177 }
1178
1179 Some(out)
1180}
1181
1182#[must_use]
1191pub fn runtime_value_btree_set_from_value<T>(value: &Value) -> Option<BTreeSet<T>>
1192where
1193 T: Ord + RuntimeValueDecode,
1194{
1195 let Value::List(values) = value else {
1196 return None;
1197 };
1198
1199 let mut out = BTreeSet::new();
1200 for value in values {
1201 let item = T::from_value(value)?;
1202 if !out.insert(item) {
1203 return None;
1204 }
1205 }
1206
1207 Some(out)
1208}
1209
1210pub fn runtime_value_map_collection_to_value<M>(map: &M, path: &'static str) -> Value
1220where
1221 M: MapCollection,
1222 M::Key: RuntimeValueEncode,
1223 M::Value: RuntimeValueEncode,
1224{
1225 let mut entries: Vec<(Value, Value)> = map
1226 .iter()
1227 .map(|(key, value)| {
1228 (
1229 RuntimeValueEncode::to_value(key),
1230 RuntimeValueEncode::to_value(value),
1231 )
1232 })
1233 .collect();
1234
1235 if let Err(err) = Value::validate_map_entries(entries.as_slice()) {
1236 debug_assert!(false, "invalid map field value for {path}: {err}");
1237 return Value::Map(entries);
1238 }
1239
1240 Value::sort_map_entries_in_place(entries.as_mut_slice());
1241
1242 for i in 1..entries.len() {
1243 let (left_key, _) = &entries[i - 1];
1244 let (right_key, _) = &entries[i];
1245 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
1246 debug_assert!(
1247 false,
1248 "duplicate map key in {path} after value-surface canonicalization",
1249 );
1250 break;
1251 }
1252 }
1253
1254 Value::Map(entries)
1255}
1256
1257#[must_use]
1266pub fn runtime_value_btree_map_from_value<K, V>(value: &Value) -> Option<BTreeMap<K, V>>
1267where
1268 K: Ord + RuntimeValueDecode,
1269 V: RuntimeValueDecode,
1270{
1271 let Value::Map(entries) = value else {
1272 return None;
1273 };
1274
1275 let normalized = Value::normalize_map_entries(entries.clone()).ok()?;
1276 if normalized.as_slice() != entries.as_slice() {
1277 return None;
1278 }
1279
1280 let mut map = BTreeMap::new();
1281 for (entry_key, entry_value) in normalized {
1282 let key = K::from_value(&entry_key)?;
1283 let value = V::from_value(&entry_value)?;
1284 map.insert(key, value);
1285 }
1286
1287 Some(map)
1288}
1289
1290#[must_use]
1299pub fn runtime_value_from_vec_into<T, I>(entries: Vec<I>) -> Vec<T>
1300where
1301 I: Into<T>,
1302{
1303 entries.into_iter().map(Into::into).collect()
1304}
1305
1306#[must_use]
1315pub fn runtime_value_from_vec_into_btree_set<T, I>(entries: Vec<I>) -> BTreeSet<T>
1316where
1317 I: Into<T>,
1318 T: Ord,
1319{
1320 entries.into_iter().map(Into::into).collect()
1321}
1322
1323#[must_use]
1332pub fn runtime_value_from_vec_into_btree_map<K, V, IK, IV>(entries: Vec<(IK, IV)>) -> BTreeMap<K, V>
1333where
1334 IK: Into<K>,
1335 IV: Into<V>,
1336 K: Ord,
1337{
1338 entries
1339 .into_iter()
1340 .map(|(key, value)| (key.into(), value.into()))
1341 .collect()
1342}
1343
1344#[must_use]
1353pub fn runtime_value_into<T, U>(value: U) -> T
1354where
1355 U: Into<T>,
1356{
1357 value.into()
1358}
1359
1360impl RuntimeValueMeta for &str {
1361 fn kind() -> RuntimeValueKind {
1362 RuntimeValueKind::Atomic
1363 }
1364}
1365
1366impl RuntimeValueEncode for &str {
1367 fn to_value(&self) -> Value {
1368 Value::Text((*self).to_string())
1369 }
1370}
1371
1372impl RuntimeValueDecode for &str {
1373 fn from_value(_value: &Value) -> Option<Self> {
1374 None
1375 }
1376}
1377
1378impl RuntimeValueMeta for String {
1379 fn kind() -> RuntimeValueKind {
1380 RuntimeValueKind::Atomic
1381 }
1382}
1383
1384impl RuntimeValueEncode for String {
1385 fn to_value(&self) -> Value {
1386 Value::Text(self.clone())
1387 }
1388}
1389
1390impl RuntimeValueDecode for String {
1391 fn from_value(value: &Value) -> Option<Self> {
1392 match value {
1393 Value::Text(v) => Some(v.clone()),
1394 _ => None,
1395 }
1396 }
1397}
1398
1399impl<T: RuntimeValueMeta> RuntimeValueMeta for Option<T> {
1400 fn kind() -> RuntimeValueKind {
1401 T::kind()
1402 }
1403}
1404
1405impl<T: RuntimeValueEncode> RuntimeValueEncode for Option<T> {
1406 fn to_value(&self) -> Value {
1407 match self {
1408 Some(v) => v.to_value(),
1409 None => Value::Null,
1410 }
1411 }
1412}
1413
1414impl<T: RuntimeValueDecode> RuntimeValueDecode for Option<T> {
1415 fn from_value(value: &Value) -> Option<Self> {
1416 if matches!(value, Value::Null) {
1417 return Some(None);
1418 }
1419
1420 T::from_value(value).map(Some)
1421 }
1422}
1423
1424impl<T: RuntimeValueMeta> RuntimeValueMeta for Box<T> {
1425 fn kind() -> RuntimeValueKind {
1426 T::kind()
1427 }
1428}
1429
1430impl<T: RuntimeValueEncode> RuntimeValueEncode for Box<T> {
1431 fn to_value(&self) -> Value {
1432 (**self).to_value()
1433 }
1434}
1435
1436impl<T: RuntimeValueDecode> RuntimeValueDecode for Box<T> {
1437 fn from_value(value: &Value) -> Option<Self> {
1438 T::from_value(value).map(Self::new)
1439 }
1440}
1441
1442impl<T> RuntimeValueMeta for Vec<T> {
1443 fn kind() -> RuntimeValueKind {
1444 RuntimeValueKind::Structured { queryable: true }
1445 }
1446}
1447
1448impl<T: RuntimeValueEncode> RuntimeValueEncode for Vec<T> {
1449 fn to_value(&self) -> Value {
1450 runtime_value_collection_to_value(self)
1451 }
1452}
1453
1454impl<T: RuntimeValueDecode> RuntimeValueDecode for Vec<T> {
1455 fn from_value(value: &Value) -> Option<Self> {
1456 runtime_value_vec_from_value(value)
1457 }
1458}
1459
1460impl<T> RuntimeValueMeta for BTreeSet<T>
1461where
1462 T: Ord,
1463{
1464 fn kind() -> RuntimeValueKind {
1465 RuntimeValueKind::Structured { queryable: true }
1466 }
1467}
1468
1469impl<T> RuntimeValueEncode for BTreeSet<T>
1470where
1471 T: Ord + RuntimeValueEncode,
1472{
1473 fn to_value(&self) -> Value {
1474 runtime_value_collection_to_value(self)
1475 }
1476}
1477
1478impl<T> RuntimeValueDecode for BTreeSet<T>
1479where
1480 T: Ord + RuntimeValueDecode,
1481{
1482 fn from_value(value: &Value) -> Option<Self> {
1483 runtime_value_btree_set_from_value(value)
1484 }
1485}
1486
1487impl<K, V> RuntimeValueMeta for BTreeMap<K, V>
1488where
1489 K: Ord,
1490{
1491 fn kind() -> RuntimeValueKind {
1492 RuntimeValueKind::Structured { queryable: true }
1493 }
1494}
1495
1496impl<K, V> RuntimeValueEncode for BTreeMap<K, V>
1497where
1498 K: Ord + RuntimeValueEncode,
1499 V: RuntimeValueEncode,
1500{
1501 fn to_value(&self) -> Value {
1502 runtime_value_map_collection_to_value(self, std::any::type_name::<Self>())
1503 }
1504}
1505
1506impl<K, V> RuntimeValueDecode for BTreeMap<K, V>
1507where
1508 K: Ord + RuntimeValueDecode,
1509 V: RuntimeValueDecode,
1510{
1511 fn from_value(value: &Value) -> Option<Self> {
1512 runtime_value_btree_map_from_value(value)
1513 }
1514}
1515
1516#[macro_export]
1518macro_rules! impl_runtime_value {
1519 ( $( $type:ty => $variant:ident ),* $(,)? ) => {
1520 $(
1521 impl RuntimeValueMeta for $type {
1522 fn kind() -> RuntimeValueKind {
1523 RuntimeValueKind::Atomic
1524 }
1525 }
1526
1527 impl RuntimeValueEncode for $type {
1528 fn to_value(&self) -> Value {
1529 Value::$variant((*self).into())
1530 }
1531 }
1532
1533 impl RuntimeValueDecode for $type {
1534 fn from_value(value: &Value) -> Option<Self> {
1535 match value {
1536 Value::$variant(v) => (*v).try_into().ok(),
1537 _ => None,
1538 }
1539 }
1540 }
1541 )*
1542 };
1543}
1544
1545impl_runtime_value!(
1546 i8 => Int64,
1547 i16 => Int64,
1548 i32 => Int64,
1549 i64 => Int64,
1550 i128 => Int128,
1551 u8 => Nat64,
1552 u16 => Nat64,
1553 u32 => Nat64,
1554 u64 => Nat64,
1555 u128 => Nat128,
1556 bool => Bool,
1557);
1558
1559pub trait Inner<T> {
1570 fn inner(&self) -> &T;
1571 fn into_inner(self) -> T;
1572}
1573
1574pub trait Repr {
1581 type Inner;
1582
1583 fn repr(&self) -> Self::Inner;
1584 fn from_repr(inner: Self::Inner) -> Self;
1585}
1586
1587pub trait Sanitizer<T> {
1598 fn sanitize(&self, value: &mut T) -> Result<(), String>;
1599
1600 fn sanitize_with_context(
1601 &self,
1602 value: &mut T,
1603 ctx: &mut dyn VisitorContext,
1604 ) -> Result<(), String> {
1605 let _ = ctx;
1606
1607 self.sanitize(value)
1608 }
1609}
1610
1611pub trait Validator<T: ?Sized> {
1618 fn validate(&self, value: &T, ctx: &mut dyn VisitorContext);
1619}