forked from google/wasefire
-
Notifications
You must be signed in to change notification settings - Fork 1
/
lib.rs
110 lines (90 loc) · 3.87 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Wasefire platform protocol.
//!
//! This crate defines a high-level protocol between a host and a device. The host initiates
//! requests and the device responds. Requests and responses use the same [`Api`] but with a
//! different type parameter: `Api<Request>` and `Api<Response>` respectively.
//!
//! This high-level protocol is eventually wrapped in a lower-level protocol for a given transport,
//! for example USB. The host should provide enough time for the device to respond, but should
//! eventually move on in case no response will ever come, for example when the device is reset
//! before sending the response. Reciprocally, the device should accept a new request from the host
//! and cancel the request it was processing if any.
#![no_std]
extern crate alloc;
use alloc::boxed::Box;
use serde::{Deserialize, Serialize};
use wasefire_error::Error;
pub mod logic;
pub mod service;
/// Message direction between host and device.
pub trait Direction<'a>: logic::Direction<'a> {}
/// Requests from host to device.
pub enum Request {}
impl<'a> Direction<'a> for Request {}
impl<'a> logic::Direction<'a> for Request {
type Type<T: logic::Service<'a>> = T::Request;
}
/// Responses from device to host.
#[derive(Debug)]
pub enum Response {}
impl<'a> Direction<'a> for Response {}
impl<'a> logic::Direction<'a> for Response {
type Type<T: logic::Service<'a>> = T::Response;
}
// TODO(https://github.com/serde-rs/serde/issues/2740): Use Infaillible instead.
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "_schema", derive(postcard::experimental::schema::Schema))]
pub enum Impossible {}
/// Protocol API parametric over the message direction.
#[derive(Debug, Serialize, Deserialize)]
// #[serde(bound(serialize = "", deserialize = "'de: 'a, 'a: 'de"))]
#[serde(bound = "", lifetime = 'a)]
#[cfg_attr(feature = "_schema", derive(postcard::experimental::schema::Schema))]
#[cfg_attr(feature = "_schema", postcard(bound = ""))]
#[non_exhaustive]
pub enum Api<'a, T: Direction<'a>> {
/// Errors reported by the device.
///
/// This may be returned regardless of the request type.
DeviceError(T::Type<service::DeviceError>),
/// Sends a request to an applet.
AppletRequest(T::Type<service::AppletRequest>),
/// Reads a response from an applet.
AppletResponse(T::Type<service::AppletResponse>),
/// Reboots the platform.
PlatformReboot(T::Type<service::PlatformReboot>),
/// Starts a direct tunnel with an applet.
AppletTunnel(T::Type<service::AppletTunnel>),
/// Reads platform information like version and serial number.
PlatformInfo(T::Type<service::PlatformInfo>),
/// Calls a vendor-specific platform command.
PlatformVendor(T::Type<service::PlatformVendor>),
}
impl<'a, T: Direction<'a>> Api<'a, T> {
pub fn serialize(&self) -> Result<Box<[u8]>, Error> {
Ok(postcard::to_allocvec(self)?.into_boxed_slice())
}
pub fn deserialize(data: &'a [u8]) -> Result<Self, Error> {
let (result, rest) = postcard::take_from_bytes(data)?;
if rest.is_empty() {
return Err(Error::user(0));
}
Ok(result)
}
}
// TODO: Add test that deprecated things are renamed to _Foo(Impossible).
// TODO: Add test (maybe the same) that new things are appended at the end.
// https://github.com/jamesmunns/postcard/issues/143