aranya_runtime/vm_policy/
protocol.rs1extern crate alloc;
2
3use alloc::{borrow::Cow, collections::BTreeMap};
4
5use aranya_crypto::DeviceId;
6use aranya_policy_vm::{
7 Struct, Value,
8 ast::{Identifier, ident},
9};
10use serde::{Deserialize, Serialize};
11
12use crate::{
13 Address, Prior,
14 command::{CmdId, Command, Priority},
15};
16
17#[derive(Debug, Serialize, Deserialize)]
19pub struct VmProtocolData<'a> {
20 pub author_id: DeviceId,
21 pub kind: Identifier,
22 #[serde(borrow)]
23 pub serialized_fields: &'a [u8],
24 #[serde(borrow)]
25 pub signature: &'a [u8],
26}
27
28#[derive(Debug)]
32pub struct VmProtocol<'a> {
33 pub id: CmdId,
34 pub priority: Priority,
35 pub parent: Prior<Address>,
36 pub policy: Option<[u8; 8]>,
37 pub data: &'a [u8],
39}
40
41impl Command for VmProtocol<'_> {
42 fn priority(&self) -> Priority {
43 self.priority.clone()
44 }
45
46 fn id(&self) -> CmdId {
47 self.id
48 }
49
50 fn parent(&self) -> Prior<Address> {
51 self.parent
52 }
53
54 fn policy(&self) -> Option<&[u8]> {
55 self.policy.as_ref().map(|p| &p[..])
56 }
57
58 fn bytes(&self) -> &[u8] {
59 self.data
60 }
61}
62
63#[derive(Clone, Debug)]
64pub struct Envelope<'a> {
65 pub parent_id: CmdId,
66 pub author_id: DeviceId,
67 pub command_id: CmdId,
68 pub payload: Cow<'a, [u8]>,
69 pub signature: Cow<'a, [u8]>,
70}
71
72impl From<Envelope<'_>> for Struct {
73 fn from(e: Envelope<'_>) -> Self {
74 Self::new(
75 ident!("Envelope"),
76 [
77 (ident!("parent_id"), e.parent_id.into()),
78 (ident!("author_id"), e.author_id.into()),
79 (ident!("command_id"), e.command_id.into()),
80 (ident!("payload"), e.payload.into_owned().into()),
81 (ident!("signature"), e.signature.into_owned().into()),
82 ],
83 )
84 }
85}
86
87impl TryFrom<Struct> for Envelope<'_> {
88 type Error = EnvelopeError;
89
90 fn try_from(
91 Struct {
92 name,
93 ref mut fields,
94 }: Struct,
95 ) -> Result<Self, Self::Error> {
96 if name != "Envelope" {
97 return Err(EnvelopeError::InvalidName(name));
98 }
99
100 Ok(Self {
101 parent_id: get(fields, "parent_id")?,
102 author_id: get(fields, "author_id")?,
103 command_id: get(fields, "command_id")?,
104 payload: Cow::Owned(get(fields, "payload")?),
105 signature: Cow::Owned(get(fields, "signature")?),
106 })
107 }
108}
109
110fn get<T: TryFrom<Value>>(
111 fields: &mut BTreeMap<Identifier, Value>,
112 key: &'static str,
113) -> Result<T, EnvelopeError> {
114 fields
115 .remove(key)
116 .ok_or(EnvelopeError::MissingField(key))?
117 .try_into()
118 .map_err(|_| EnvelopeError::InvalidType(key))
119}
120
121#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
122pub enum EnvelopeError {
123 #[error("invalid struct name {0:?}")]
124 InvalidName(Identifier),
125 #[error("missing field {0:?}")]
126 MissingField(&'static str),
127 #[error("invalid type for field {0:?}")]
128 InvalidType(&'static str),
129}