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