aranya_policy_module/
data.rs

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