-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move serde_extensions module into trussed-core
- Loading branch information
1 parent
0975eb4
commit d095a53
Showing
6 changed files
with
136 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
//! Extensions to the core Trussed syscalls. | ||
//! | ||
//! *Requires the `serde-extensions` feature.* | ||
//! | ||
//! This module makes it possible to add additional syscalls to Trussed by implementing the | ||
//! [`Extension`][] trait. Extension requests and replies are serialized to | ||
//! [`Request::SerdeExtension`][] and [`Reply::SerdeExtension`][]. | ||
//! | ||
//! [`Request::SerdeExtension`]: `crate::api::Request::SerdeExtension` | ||
//! [`Reply::SerdeExtension`]: `crate::api::Reply::SerdeExtension` | ||
use core::{marker::PhantomData, task::Poll}; | ||
|
||
use serde::{de::DeserializeOwned, Serialize}; | ||
|
||
use crate::{ | ||
api::{reply, request}, | ||
client::{ClientError, FutureResult, PollClient}, | ||
error::Error, | ||
types::Bytes, | ||
}; | ||
|
||
/// A Trussed API extension. | ||
pub trait Extension { | ||
/// The requests supported by this extension. | ||
type Request: DeserializeOwned + Serialize; | ||
/// The replies supported by this extension. | ||
type Reply: DeserializeOwned + Serialize; | ||
|
||
/// Deserialize an extension request. | ||
/// | ||
/// This function can be used to deserialize requests that have been serialized by | ||
/// [`ExtensionClient`][]. The format is not guaranteed to be stable. | ||
fn deserialize_request(request: &request::SerdeExtension) -> Result<Self::Request, Error> { | ||
postcard::from_bytes(&request.request).map_err(|_| Error::InvalidSerializedRequest) | ||
} | ||
|
||
/// Serialize an extension reply. | ||
/// | ||
/// Replies that are serialized with this function can be deserialized by | ||
/// [`ExtensionClient`][]. The format is not guaranteed to be stable. | ||
fn serialize_reply(reply: &Self::Reply) -> Result<reply::SerdeExtension, Error> { | ||
postcard::to_vec(reply) | ||
.map(Bytes::from) | ||
.map(|reply| reply::SerdeExtension { reply }) | ||
.map_err(|_| Error::ReplySerializationFailure) | ||
} | ||
} | ||
|
||
/// Executes extension requests. | ||
/// | ||
/// Instead of using this trait directly, extensions should define their own traits that extend | ||
/// this trait and use the `extension` function to execute extension requests. | ||
pub trait ExtensionClient<E: Extension>: PollClient { | ||
/// Returns the ID for the `E` extension as defined by the runner. | ||
fn id() -> u8; | ||
|
||
/// Executes an extension request. | ||
/// | ||
/// Applications should not call this method directly and instead use a trait provided by the | ||
/// extension. | ||
fn extension<Rq, Rp>(&mut self, request: Rq) -> ExtensionResult<'_, E, Rp, Self> | ||
where | ||
Rq: Into<E::Request>, | ||
Rp: TryFrom<E::Reply, Error = Error>, | ||
{ | ||
self.request(request::SerdeExtension { | ||
id: Self::id(), | ||
request: postcard::to_vec(&request.into()) | ||
.map(Bytes::from) | ||
.map_err(|_| ClientError::SerializationFailed)?, | ||
}) | ||
.map(From::from) | ||
} | ||
} | ||
|
||
/// A result returned by [`ExtensionClient`][] and clients using it. | ||
pub type ExtensionResult<'a, E, T, C> = Result<ExtensionFutureResult<'a, E, T, C>, ClientError>; | ||
|
||
#[must_use = "Syscalls must be polled with the `syscall` macro"] | ||
/// A future of an [`ExtensionResult`][]. | ||
pub struct ExtensionFutureResult<'c, E, T, C: ?Sized> { | ||
client: &'c mut C, | ||
__: PhantomData<(E, T)>, | ||
} | ||
|
||
impl<'c, E, T, C: ?Sized> ExtensionFutureResult<'c, E, T, C> { | ||
fn new(client: &'c mut C) -> Self { | ||
Self { | ||
client, | ||
__: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
impl<'c, E, T, C> ExtensionFutureResult<'c, E, T, C> | ||
where | ||
E: Extension, | ||
T: TryFrom<E::Reply, Error = Error>, | ||
C: PollClient, | ||
{ | ||
pub fn poll(&mut self) -> Poll<Result<T, Error>> { | ||
self.client.poll().map(|result| { | ||
result.and_then(|reply| { | ||
let reply = reply::SerdeExtension::try_from(reply)?; | ||
let reply: E::Reply = postcard::from_bytes(&reply.reply) | ||
.map_err(|_| Error::InvalidSerializedReply)?; | ||
reply.try_into() | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
impl<'c, E, T, C> From<FutureResult<'c, reply::SerdeExtension, C>> | ||
for ExtensionFutureResult<'c, E, T, C> | ||
where | ||
C: PollClient + ?Sized, | ||
{ | ||
fn from(result: FutureResult<'c, reply::SerdeExtension, C>) -> Self { | ||
Self::new(result.client) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters