Skip to main content

wasefire_protocol/
applet.rs

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use alloc::borrow::Cow;
16
17use wasefire_error::{Code, Error};
18use wasefire_wire::Wire;
19
20use crate::common::{Hexa, Name};
21
22#[derive(Debug, Default, Clone, Wire)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct Metadata0<'a> {
25    /// Name of the applet.
26    pub name: Name<'a>,
27
28    /// Version of the applet.
29    pub version: Hexa<'a>,
30}
31
32impl<'a> Metadata0<'a> {
33    /// Extracts the metadata suffix from an applet payload.
34    ///
35    /// The payload is the concatenation of:
36    /// - The applet (N bytes). After the call, the payload will be the applet.
37    /// - The metadata.
38    /// - The value N encoded as 4 bytes in big-endian.
39    pub fn new(payload: &mut &'a [u8]) -> Result<Metadata0<'a>, Error> {
40        let (data, len) =
41            payload.split_last_chunk::<4>().ok_or(Error::user(Code::InvalidLength))?;
42        let len = u32::from_be_bytes(*len) as usize;
43        let (applet, metadata) =
44            data.split_at_checked(len).ok_or(Error::user(Code::InvalidState))?;
45        *payload = applet;
46        wasefire_wire::decode(metadata)
47    }
48}
49
50#[derive(Debug, Wire)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52pub struct Request<'a> {
53    pub applet_id: AppletId,
54    pub request: Cow<'a, [u8]>,
55}
56
57#[derive(Debug, Copy, Clone, Wire)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59pub struct AppletId;
60
61#[derive(Debug, Wire)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub struct Tunnel<'a> {
64    pub applet_id: AppletId,
65    pub delimiter: Cow<'a, [u8]>,
66}
67
68#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Wire)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub enum ExitStatus {
71    /// The applet exited successfully.
72    Exit,
73
74    /// The applet aborted (e.g. it panicked).
75    Abort,
76
77    /// The applet trapped (e.g. bad memory access).
78    Trap,
79
80    /// The applet was killed (e.g. it was uninstalled).
81    Kill,
82}
83
84#[cfg(feature = "host")]
85impl core::fmt::Display for ExitStatus {
86    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
87        match self {
88            ExitStatus::Exit => write!(f, "The applet exited"),
89            ExitStatus::Abort => write!(f, "The applet aborted"),
90            ExitStatus::Trap => write!(f, "The applet trapped"),
91            ExitStatus::Kill => write!(f, "The applet was killed"),
92        }
93    }
94}