use core::{marker::PhantomData, task::Poll};
use serde::{de::DeserializeOwned, Serialize};
use crate::{
api::{reply, request},
client::{ClientError, FutureResult, PollClient},
error::Error,
types::Bytes,
};
pub(crate) fn postcard_serialize_bytes<T: serde::Serialize, const N: usize>(
object: &T,
) -> postcard::Result<Bytes<N>> {
let mut vec = Bytes::new();
vec.resize_to_capacity();
let serialized = postcard::to_slice(object, &mut vec)?.len();
vec.resize(serialized, 0).unwrap();
Ok(vec)
}
pub trait Extension {
type Request: DeserializeOwned + Serialize;
type Reply: DeserializeOwned + Serialize;
#[inline(never)]
fn serialize_request(
id: u8,
request: &Self::Request,
) -> Result<request::SerdeExtension, ClientError> {
postcard_serialize_bytes(request)
.map(|request| request::SerdeExtension { id, request })
.map_err(|_| ClientError::SerializationFailed)
}
#[inline(never)]
fn deserialize_request(request: &request::SerdeExtension) -> Result<Self::Request, Error> {
postcard::from_bytes(&request.request).map_err(|_| Error::InvalidSerializedRequest)
}
#[inline(never)]
fn serialize_reply(reply: &Self::Reply) -> Result<reply::SerdeExtension, Error> {
postcard_serialize_bytes(reply)
.map(|reply| reply::SerdeExtension { reply })
.map_err(|_| Error::ReplySerializationFailure)
}
#[inline(never)]
fn deserialize_reply(reply: &reply::SerdeExtension) -> Result<Self::Reply, Error> {
postcard::from_bytes(&reply.reply).map_err(|_| Error::InvalidSerializedReply)
}
}
pub trait ExtensionClient<E: Extension>: PollClient {
fn id() -> u8;
fn extension<Rq, Rp>(&mut self, request: Rq) -> ExtensionResult<'_, E, Rp, Self>
where
Rq: Into<E::Request>,
Rp: TryFrom<E::Reply, Error = Error>,
{
let request = E::serialize_request(Self::id(), &request.into())?;
self.request(request).map(From::from)
}
}
pub type ExtensionResult<'a, E, T, C> = Result<ExtensionFutureResult<'a, E, T, C>, ClientError>;
#[must_use = "Syscalls must be polled with the `syscall` macro"]
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<E, T, C> ExtensionFutureResult<'_, 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 = E::deserialize_reply(&reply)?;
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)
}
}