Skip to main content

aranya_policy_module/
data.rs

1extern crate alloc;
2
3use alloc::{
4    borrow::ToOwned as _, boxed::Box, collections::BTreeMap, format, string::String, vec, vec::Vec,
5};
6use core::fmt::{self, Display};
7
8pub use aranya_id::BaseId;
9use aranya_id::{Id, IdTag};
10use aranya_policy_ast::{Ident, Identifier, Span, Text, TypeKind, VType};
11use serde::{Deserialize, Serialize};
12
13use super::ffi::Type;
14
15#[derive(Debug, thiserror::Error)]
16/// Indicates that the Value conversion has failed
17pub enum ValueConversionError {
18    /// A conversion was attempted to a type that is not compatible with this Value
19    #[error("expected type {want}, but got {got}: {msg}")]
20    InvalidType {
21        /// Expected type name
22        want: String,
23        /// Received type name
24        got: String,
25        /// Extra information
26        msg: String,
27    },
28    /// A struct conversion found a field mismatch between types
29    #[error("invalid struct member `{0}`")]
30    InvalidStructMember(Identifier),
31    /// The target type does not have sufficient range to represent this Value
32    #[error("value out of range")]
33    OutOfRange,
34    /// Some internal state is corrupt
35    #[error("bad state")]
36    BadState,
37}
38
39impl ValueConversionError {
40    /// Constructs an `InvalidType` error
41    pub fn invalid_type(
42        want: impl Into<String>,
43        got: impl Into<String>,
44        msg: impl Into<String>,
45    ) -> Self {
46        Self::InvalidType {
47            want: want.into(),
48            got: got.into(),
49            msg: msg.into(),
50        }
51    }
52}
53
54/// Allows a type to be used by FFI derive.
55// TODO(eric): move this into `super::ffi`?
56pub trait Typed {
57    /// Indicates the type of the type.
58    const TYPE: Type<'static>;
59}
60
61macro_rules! impl_typed {
62    ($name:ty => $type:ident) => {
63        impl Typed for $name {
64            const TYPE: Type<'static> = Type::$type;
65        }
66    };
67}
68
69impl_typed!(Text => String);
70
71impl_typed!(Vec<u8> => Bytes);
72impl_typed!(&[u8] => Bytes);
73
74impl_typed!(isize => Int);
75impl_typed!(i64 => Int);
76impl_typed!(i32 => Int);
77impl_typed!(i16 => Int);
78impl_typed!(i8 => Int);
79
80impl_typed!(usize => Int);
81impl_typed!(u64 => Int);
82impl_typed!(u32 => Int);
83impl_typed!(u16 => Int);
84impl_typed!(u8 => Int);
85
86impl_typed!(bool => Bool);
87
88impl<Tag: IdTag> Typed for Id<Tag> {
89    const TYPE: Type<'static> = Type::Id;
90}
91
92impl<T: Typed> Typed for Option<T> {
93    const TYPE: Type<'static> = Type::Optional(const { &T::TYPE });
94}
95
96/// All of the value types allowed in the VM
97#[derive(
98    Debug,
99    Clone,
100    PartialEq,
101    Eq,
102    Serialize,
103    Deserialize,
104    rkyv::Archive,
105    rkyv::Deserialize,
106    rkyv::Serialize,
107)]
108#[rkyv(serialize_bounds(
109    __S: rkyv::ser::Writer + rkyv::ser::Allocator,
110    __S::Error: rkyv::rancor::Source,
111))]
112#[rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))]
113#[rkyv(bytecheck(
114    bounds(
115        __C: rkyv::validation::ArchiveContext,
116        __C::Error: rkyv::rancor::Source,
117    )
118))]
119pub enum Value {
120    /// Integer (64-bit signed)
121    Int(i64),
122    /// Boolean
123    Bool(bool),
124    /// String (UTF-8)
125    String(Text),
126    /// Bytes
127    Bytes(Vec<u8>),
128    /// Struct
129    Struct(#[rkyv(omit_bounds)] Struct),
130    /// Fact
131    Fact(Fact),
132    /// A unique identifier.
133    Id(BaseId),
134    /// Enumeration value
135    Enum(Identifier, i64),
136    /// Textual Identifier (name)
137    Identifier(Identifier),
138    /// Optional value
139    Option(#[rkyv(omit_bounds)] Option<Box<Self>>),
140}
141
142impl Value {
143    /// Shorthand for `Self::Option(None)`.
144    pub const NONE: Self = Self::Option(None);
145}
146
147/// Trait for converting from a [`Value`], similar to [`TryFrom<Value>`].
148///
149/// This trait allows us to add a blanket impl for `Option`, which we cannot
150/// do for `TryFrom<Value>` because of overlap and foreign type restrictions.
151pub trait TryFromValue: Sized {
152    /// Tries to convert a [`Value`] into `Self`.
153    fn try_from_value(value: Value) -> Result<Self, ValueConversionError>;
154}
155
156impl<T: TryFromValue> TryFromValue for Option<T> {
157    fn try_from_value(value: Value) -> Result<Self, ValueConversionError> {
158        let Value::Option(opt) = value else {
159            return Err(ValueConversionError::InvalidType {
160                want: "Option".into(),
161                got: value.type_name(),
162                msg: format!("Value -> {}", core::any::type_name::<Self>()),
163            });
164        };
165        opt.map(|v| T::try_from_value(*v)).transpose()
166    }
167}
168
169impl<T: TryFrom<Value, Error = ValueConversionError>> TryFromValue for T {
170    fn try_from_value(value: Value) -> Result<Self, ValueConversionError> {
171        Self::try_from(value)
172    }
173}
174
175/// Like `AsMut`, but fallible.
176pub trait TryAsMut<T: ?Sized> {
177    /// The error result.
178    type Error;
179
180    /// Converts this type into a mutable reference of the
181    /// (usually inferred) input type.
182    fn try_as_mut(&mut self) -> Result<&mut T, Self::Error>;
183}
184
185impl Value {
186    /// Get the [`TypeKind`], if possible.
187    pub fn vtype(&self) -> Option<TypeKind> {
188        match self {
189            Self::Int(_) => Some(TypeKind::Int),
190            Self::Bool(_) => Some(TypeKind::Bool),
191            Self::String(_) => Some(TypeKind::String),
192            Self::Bytes(_) => Some(TypeKind::Bytes),
193            Self::Id(_) => Some(TypeKind::Id),
194            Self::Enum(name, _) => Some(TypeKind::Enum(Ident {
195                name: name.to_owned(),
196                span: Span::default(),
197            })),
198            Self::Struct(s) => Some(TypeKind::Struct(Ident {
199                name: s.name.clone(),
200                span: Span::default(),
201            })),
202            _ => None,
203        }
204    }
205
206    /// Returns a string representing the value's type.
207    pub fn type_name(&self) -> String {
208        match self {
209            Self::Int(_) => String::from("Int"),
210            Self::Bool(_) => String::from("Bool"),
211            Self::String(_) => String::from("String"),
212            Self::Bytes(_) => String::from("Bytes"),
213            Self::Struct(s) => format!("Struct {}", s.name),
214            Self::Fact(f) => format!("Fact {}", f.name),
215            Self::Id(_) => String::from("Id"),
216            Self::Enum(name, _) => format!("Enum {}", name),
217            Self::Identifier(_) => String::from("Identifier"),
218            Self::Option(Some(inner)) => format!("Option[{}]", inner.type_name()),
219            Self::Option(None) => String::from("Option[_]"),
220        }
221    }
222
223    /// Checks to see if a [`Value`] matches some [`VType`]
224    /// ```
225    /// use aranya_policy_ast::{Span, TypeKind, VType};
226    /// use aranya_policy_module::Value;
227    ///
228    /// let value = Value::Int(1);
229    /// let int_type = VType {
230    ///     kind: TypeKind::Int,
231    ///     span: Span::empty(),
232    /// };
233    ///
234    /// assert!(value.fits_type(&int_type));
235    /// ```
236    pub fn fits_type(&self, expected_type: &VType) -> bool {
237        use aranya_policy_ast::TypeKind;
238        match (self, &expected_type.kind) {
239            (Self::Int(_), TypeKind::Int) => true,
240            (Self::Bool(_), TypeKind::Bool) => true,
241            (Self::String(_), TypeKind::String) => true,
242            (Self::Bytes(_), TypeKind::Bytes) => true,
243            (Self::Struct(s), TypeKind::Struct(ident)) => s.name == ident.name,
244            (Self::Id(_), TypeKind::Id) => true,
245            (Self::Enum(name, _), TypeKind::Enum(ident)) => *name == ident.name,
246            (Self::Option(Some(value)), TypeKind::Optional(ty)) => value.fits_type(ty),
247            (Self::Option(None), TypeKind::Optional(_)) => true,
248            _ => false,
249        }
250    }
251}
252
253impl<T: Into<Self>> From<Option<T>> for Value {
254    fn from(value: Option<T>) -> Self {
255        Self::Option(value.map(Into::into).map(Box::new))
256    }
257}
258
259impl From<i64> for Value {
260    fn from(value: i64) -> Self {
261        Self::Int(value)
262    }
263}
264
265impl From<bool> for Value {
266    fn from(value: bool) -> Self {
267        Self::Bool(value)
268    }
269}
270
271impl From<Text> for Value {
272    fn from(value: Text) -> Self {
273        Self::String(value)
274    }
275}
276
277impl From<Identifier> for Value {
278    fn from(value: Identifier) -> Self {
279        Self::Identifier(value)
280    }
281}
282
283impl From<&[u8]> for Value {
284    fn from(value: &[u8]) -> Self {
285        Self::Bytes(value.to_owned())
286    }
287}
288
289impl From<Vec<u8>> for Value {
290    fn from(value: Vec<u8>) -> Self {
291        Self::Bytes(value)
292    }
293}
294
295impl From<Struct> for Value {
296    fn from(value: Struct) -> Self {
297        Self::Struct(value)
298    }
299}
300
301impl From<Fact> for Value {
302    fn from(value: Fact) -> Self {
303        Self::Fact(value)
304    }
305}
306
307impl<Tag: IdTag> From<Id<Tag>> for Value {
308    fn from(id: Id<Tag>) -> Self {
309        Self::Id(id.as_base())
310    }
311}
312
313impl TryFrom<Value> for i64 {
314    type Error = ValueConversionError;
315
316    fn try_from(value: Value) -> Result<Self, Self::Error> {
317        if let Value::Int(i) = value {
318            return Ok(i);
319        }
320        Err(ValueConversionError::invalid_type(
321            "Int",
322            value.type_name(),
323            "Value -> i64",
324        ))
325    }
326}
327
328impl TryFrom<Value> for bool {
329    type Error = ValueConversionError;
330
331    fn try_from(value: Value) -> Result<Self, Self::Error> {
332        if let Value::Bool(b) = value {
333            return Ok(b);
334        }
335        Err(ValueConversionError::invalid_type(
336            "Bool",
337            value.type_name(),
338            "Value -> bool",
339        ))
340    }
341}
342
343impl TryFrom<Value> for Text {
344    type Error = ValueConversionError;
345
346    fn try_from(value: Value) -> Result<Self, Self::Error> {
347        if let Value::String(s) = value {
348            return Ok(s);
349        }
350        Err(ValueConversionError::invalid_type(
351            "String",
352            value.type_name(),
353            "Value -> Text",
354        ))
355    }
356}
357
358impl TryFrom<Value> for Identifier {
359    type Error = ValueConversionError;
360
361    fn try_from(value: Value) -> Result<Self, Self::Error> {
362        let Value::Identifier(text) = value else {
363            return Err(ValueConversionError::invalid_type(
364                "Identifier",
365                value.type_name(),
366                "Value -> Identifier",
367            ));
368        };
369        Ok(text)
370    }
371}
372
373impl TryFrom<Value> for Vec<u8> {
374    type Error = ValueConversionError;
375
376    fn try_from(value: Value) -> Result<Self, Self::Error> {
377        if let Value::Bytes(v) = value {
378            return Ok(v);
379        }
380        Err(ValueConversionError::invalid_type(
381            "Bytes",
382            value.type_name(),
383            "Value -> Vec<u8>",
384        ))
385    }
386}
387
388impl TryFrom<Value> for Struct {
389    type Error = ValueConversionError;
390
391    fn try_from(value: Value) -> Result<Self, Self::Error> {
392        if let Value::Struct(s) = value {
393            return Ok(s);
394        }
395        Err(ValueConversionError::invalid_type(
396            "Struct",
397            value.type_name(),
398            "Value -> Struct",
399        ))
400    }
401}
402
403impl TryFrom<Value> for Fact {
404    type Error = ValueConversionError;
405
406    fn try_from(value: Value) -> Result<Self, Self::Error> {
407        if let Value::Fact(f) = value {
408            return Ok(f);
409        }
410        Err(ValueConversionError::invalid_type(
411            "Fact",
412            value.type_name(),
413            "Value -> Fact",
414        ))
415    }
416}
417
418impl<Tag: IdTag> TryFrom<Value> for Id<Tag> {
419    type Error = ValueConversionError;
420
421    fn try_from(value: Value) -> Result<Self, Self::Error> {
422        if let Value::Id(id) = value {
423            Ok(Self::from_base(id))
424        } else {
425            Err(ValueConversionError::invalid_type(
426                "Id",
427                value.type_name(),
428                "Value -> Id",
429            ))
430        }
431    }
432}
433
434impl TryAsMut<i64> for Value {
435    type Error = ValueConversionError;
436    fn try_as_mut(&mut self) -> Result<&mut i64, Self::Error> {
437        if let Self::Int(s) = self {
438            return Ok(s);
439        }
440        Err(ValueConversionError::invalid_type(
441            "i64",
442            self.type_name(),
443            "Value -> i64",
444        ))
445    }
446}
447
448impl TryAsMut<bool> for Value {
449    type Error = ValueConversionError;
450    fn try_as_mut(&mut self) -> Result<&mut bool, Self::Error> {
451        if let Self::Bool(b) = self {
452            return Ok(b);
453        }
454        Err(ValueConversionError::invalid_type(
455            "bool",
456            self.type_name(),
457            "Value -> bool",
458        ))
459    }
460}
461
462impl TryAsMut<[u8]> for Value {
463    type Error = ValueConversionError;
464    fn try_as_mut(&mut self) -> Result<&mut [u8], Self::Error> {
465        if let Self::Bytes(v) = self {
466            return Ok(v);
467        }
468        Err(ValueConversionError::invalid_type(
469            "Vec<u8>",
470            self.type_name(),
471            "Value -> [u8]",
472        ))
473    }
474}
475
476impl TryAsMut<Struct> for Value {
477    type Error = ValueConversionError;
478    fn try_as_mut(&mut self) -> Result<&mut Struct, Self::Error> {
479        if let Self::Struct(s) = self {
480            return Ok(s);
481        }
482        Err(ValueConversionError::invalid_type(
483            "Struct",
484            self.type_name(),
485            "Value -> Struct",
486        ))
487    }
488}
489
490impl TryAsMut<Fact> for Value {
491    type Error = ValueConversionError;
492    fn try_as_mut(&mut self) -> Result<&mut Fact, Self::Error> {
493        if let Self::Fact(f) = self {
494            return Ok(f);
495        }
496        Err(ValueConversionError::invalid_type(
497            "Fact",
498            self.type_name(),
499            "Value -> Fact",
500        ))
501    }
502}
503
504impl Display for Value {
505    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
506        match self {
507            Self::Int(i) => write!(f, "{}", i),
508            Self::Bool(b) => write!(f, "{}", b),
509            Self::String(s) => write!(f, "\"{}\"", s),
510            Self::Bytes(v) => {
511                write!(f, "b:")?;
512                for b in v {
513                    write!(f, "{:02X}", b)?;
514                }
515                Ok(())
516            }
517            Self::Struct(s) => s.fmt(f),
518            Self::Fact(fa) => fa.fmt(f),
519            Self::Id(id) => id.fmt(f),
520            Self::Enum(name, value) => write!(f, "{name}::{value}"),
521            Self::Identifier(name) => write!(f, "{name}"),
522            Self::Option(Some(v)) => write!(f, "Some({v})"),
523            Self::Option(None) => write!(f, "None"),
524        }
525    }
526}
527
528/// The subset of Values that can be hashed. Only these types of values
529/// can be used in the key portion of a Fact.
530#[derive(
531    Debug,
532    Clone,
533    PartialEq,
534    Eq,
535    Hash,
536    PartialOrd,
537    Ord,
538    Serialize,
539    Deserialize,
540    rkyv::Archive,
541    rkyv::Deserialize,
542    rkyv::Serialize,
543)]
544#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
545pub enum HashableValue {
546    /// An integer.
547    Int(i64),
548    /// A bool.
549    Bool(bool),
550    /// A string.
551    String(Text),
552    /// A unique identifier.
553    Id(BaseId),
554    /// Enum
555    Enum(Identifier, i64),
556}
557
558impl HashableValue {
559    /// Get the [`TypeKind`]. Unlike the Value version, this cannot
560    /// fail.
561    pub fn vtype(&self) -> TypeKind {
562        use aranya_policy_ast::TypeKind;
563        match self {
564            Self::Int(_) => TypeKind::Int,
565            Self::Bool(_) => TypeKind::Bool,
566            Self::String(_) => TypeKind::String,
567            Self::Id(_) => TypeKind::Id,
568            Self::Enum(id, _) => TypeKind::Enum(Ident {
569                name: id.clone(),
570                span: Span::default(),
571            }),
572        }
573    }
574}
575
576impl TryFrom<Value> for HashableValue {
577    type Error = ValueConversionError;
578
579    fn try_from(value: Value) -> Result<Self, Self::Error> {
580        match value {
581            Value::Int(v) => Ok(Self::Int(v)),
582            Value::Bool(v) => Ok(Self::Bool(v)),
583            Value::String(v) => Ok(Self::String(v)),
584            Value::Id(v) => Ok(Self::Id(v)),
585            Value::Enum(id, value) => Ok(Self::Enum(id, value)),
586            _ => Err(ValueConversionError::invalid_type(
587                "Int | Bool | String | Id | Enum",
588                value.type_name(),
589                "Value -> HashableValue",
590            )),
591        }
592    }
593}
594
595impl From<HashableValue> for Value {
596    fn from(value: HashableValue) -> Self {
597        match value {
598            HashableValue::Int(v) => Self::Int(v),
599            HashableValue::Bool(v) => Self::Bool(v),
600            HashableValue::String(v) => Self::String(v),
601            HashableValue::Id(v) => Self::Id(v),
602            HashableValue::Enum(id, value) => Self::Enum(id, value),
603        }
604    }
605}
606
607impl Display for HashableValue {
608    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609        let real_value: Value = self.to_owned().into();
610        write!(f, "{}", real_value)
611    }
612}
613
614/// One labeled value in a fact key. A sequence of FactKeys mapped to
615/// a sequence of FactValues comprises a Fact.
616#[derive(
617    Debug,
618    Clone,
619    PartialEq,
620    Eq,
621    PartialOrd,
622    Ord,
623    Hash,
624    Serialize,
625    Deserialize,
626    rkyv::Archive,
627    rkyv::Deserialize,
628    rkyv::Serialize,
629)]
630#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
631pub struct FactKey {
632    /// key name
633    pub identifier: Identifier,
634    /// key value
635    pub value: HashableValue,
636}
637
638impl FactKey {
639    /// Creates a new fact key.
640    pub fn new(name: Identifier, value: HashableValue) -> Self {
641        Self {
642            identifier: name,
643            value,
644        }
645    }
646}
647
648impl Display for FactKey {
649    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
650        write!(f, "{}: {}", self.identifier, self.value)
651    }
652}
653
654/// One labeled value in a fact value.
655#[derive(
656    Debug,
657    Clone,
658    PartialEq,
659    Eq,
660    Serialize,
661    Deserialize,
662    rkyv::Archive,
663    rkyv::Deserialize,
664    rkyv::Serialize,
665)]
666pub struct FactValue {
667    /// value name
668    pub identifier: Identifier,
669    /// value
670    pub value: Value,
671}
672
673impl FactValue {
674    /// Creates a new fact value.
675    pub fn new(name: Identifier, value: Value) -> Self {
676        Self {
677            identifier: name,
678            value,
679        }
680    }
681}
682
683impl Display for FactValue {
684    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685        write!(f, "{}: {}", self.identifier, self.value)
686    }
687}
688
689/// A list of fact keys.
690pub type FactKeyList = Vec<FactKey>;
691
692/// A list of fact values.
693pub type FactValueList = Vec<FactValue>;
694
695/// A generic key/value pair. Used for Effects and Command fields.
696/// Technically identical to a FactValue but separate to distinguish
697/// usage.
698#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
699pub struct KVPair(Identifier, Value);
700
701impl KVPair {
702    /// Creates a key-value pair.
703    pub fn new(key: Identifier, value: Value) -> Self {
704        Self(key, value)
705    }
706
707    /// Creates a key-value pair with an integer value.
708    pub fn new_int(key: Identifier, value: i64) -> Self {
709        Self(key, Value::Int(value))
710    }
711
712    /// Returns the key half of the key-value pair.
713    pub fn key(&self) -> &Identifier {
714        &self.0
715    }
716
717    /// Returns the value half of the key-value pair.
718    pub fn value(&self) -> &Value {
719        &self.1
720    }
721}
722
723impl Display for KVPair {
724    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
725        write!(f, "{}: {}", self.0, self.1)
726    }
727}
728
729impl From<KVPair> for (Identifier, Value) {
730    fn from(kv: KVPair) -> Self {
731        (kv.0, kv.1)
732    }
733}
734
735impl From<&KVPair> for (Identifier, Value) {
736    fn from(value: &KVPair) -> Self {
737        (value.0.clone(), value.1.clone())
738    }
739}
740
741impl From<FactKey> for KVPair {
742    fn from(value: FactKey) -> Self {
743        Self(value.identifier, value.value.into())
744    }
745}
746
747impl From<FactValue> for KVPair {
748    fn from(value: FactValue) -> Self {
749        Self(value.identifier, value.value)
750    }
751}
752
753/// A Fact
754#[derive(
755    Debug,
756    Clone,
757    PartialEq,
758    Eq,
759    Serialize,
760    Deserialize,
761    rkyv::Archive,
762    rkyv::Deserialize,
763    rkyv::Serialize,
764)]
765#[rkyv(serialize_bounds(
766    __S: rkyv::ser::Writer + rkyv::ser::Allocator,
767    __S::Error: rkyv::rancor::Source,
768))]
769#[rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))]
770#[rkyv(bytecheck(
771    bounds(
772        __C: rkyv::validation::ArchiveContext,
773        __C::Error: rkyv::rancor::Source,
774    )
775))]
776pub struct Fact {
777    /// The name of the fact
778    pub name: Identifier,
779    /// The keys of the fact
780    #[rkyv(omit_bounds)]
781    pub keys: FactKeyList,
782    /// The values of the fact
783    #[rkyv(omit_bounds)]
784    pub values: FactValueList,
785}
786
787impl Fact {
788    /// Creates a fact.
789    pub fn new(name: Identifier) -> Self {
790        Self {
791            name,
792            keys: vec![],
793            values: vec![],
794        }
795    }
796
797    /// Sets the fact's key.
798    pub fn set_key<V>(&mut self, name: Identifier, value: V)
799    where
800        V: Into<HashableValue>,
801    {
802        match self.keys.iter_mut().find(|e| e.identifier == name) {
803            None => self.keys.push(FactKey::new(name, value.into())),
804            Some(e) => e.value = value.into(),
805        }
806    }
807
808    /// Sets the fact's value.
809    pub fn set_value<V>(&mut self, name: Identifier, value: V)
810    where
811        V: Into<Value>,
812    {
813        match self.values.iter_mut().find(|e| e.identifier == name) {
814            None => self.values.push(FactValue {
815                identifier: name,
816                value: value.into(),
817            }),
818            Some(e) => e.value = value.into(),
819        }
820    }
821}
822
823impl Display for Fact {
824    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
825        write!(f, "{}[", self.name)?;
826        let mut i = false;
827        for FactKey {
828            identifier: k,
829            value: v,
830        } in &self.keys
831        {
832            if i {
833                write!(f, ", ")?;
834            }
835            i = true;
836            write!(f, "{}: {}", k, v)?;
837        }
838        write!(f, "]=>{{")?;
839        i = false;
840        for FactValue {
841            identifier: k,
842            value: v,
843        } in &self.values
844        {
845            if i {
846                write!(f, ", ")?;
847            }
848            i = true;
849            write!(f, "{}: {}", k, v)?;
850        }
851        write!(f, " }}")
852    }
853}
854
855/// A Struct value
856#[derive(
857    Debug,
858    Clone,
859    PartialEq,
860    Eq,
861    Serialize,
862    Deserialize,
863    rkyv::Archive,
864    rkyv::Deserialize,
865    rkyv::Serialize,
866)]
867#[rkyv(serialize_bounds(
868    __S: rkyv::ser::Writer + rkyv::ser::Allocator,
869    __S::Error: rkyv::rancor::Source,
870))]
871#[rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))]
872#[rkyv(bytecheck(
873    bounds(
874        __C: rkyv::validation::ArchiveContext,
875        __C::Error: rkyv::rancor::Source,
876    )
877))]
878pub struct Struct {
879    /// The name of the struct
880    pub name: Identifier,
881    /// the fields of the struct
882    #[rkyv(omit_bounds)]
883    pub fields: BTreeMap<Identifier, Value>,
884}
885
886impl Struct {
887    /// Creates a struct.
888    pub fn new(
889        name: Identifier,
890        fields: impl IntoIterator<Item = impl Into<(Identifier, Value)>>,
891    ) -> Self {
892        Self {
893            name,
894            fields: fields.into_iter().map(Into::into).collect(),
895        }
896    }
897}
898
899impl Display for Struct {
900    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
901        write!(f, "{}{{", self.name)?;
902        let mut i = false;
903        for (k, v) in &self.fields {
904            if i {
905                write!(f, ", ")?;
906            }
907            i = true;
908            write!(f, "{}: {}", k, v)?;
909        }
910        write!(f, "}}")
911    }
912}
913
914#[cfg(test)]
915mod test {
916    use crate::{TryFromValue as _, Value};
917
918    #[test]
919    fn test_option_error() {
920        let err = <Option<i64>>::try_from_value(Value::Bool(true)).unwrap_err();
921        assert_eq!(
922            err.to_string(),
923            "expected type Option, but got Bool: Value -> core::option::Option<i64>"
924        );
925    }
926}