diff --git a/src/backend.rs b/src/backend.rs index db3e9046403..eb3b6ff1b40 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -92,3 +92,60 @@ impl TryFrom for NoId { Err(Error::InternalError) } } + +/// Helper type for optional backends. +/// +/// If the backend is `None`, [`Error::RequestNotAvailable`][] is returned. +#[derive(Debug)] +pub struct OptionalBackend(Option); + +impl OptionalBackend { + /// Crates a new optional backend from an `Option`. + pub fn new(backend: Option) -> Self { + Self(backend) + } + + /// Returns a mutable reference to the wrapped backend or [`Error::RequestNotAvailable`][] if + /// it is `None`. + pub fn inner(&mut self) -> Result<&mut T, Error> { + self.0.as_mut().ok_or(Error::RequestNotAvailable) + } + + /// Returns the wrapped backend. + pub fn into_inner(self) -> Option { + self.0 + } +} + +impl Default for OptionalBackend { + fn default() -> Self { + Self(None) + } +} + +impl From for OptionalBackend { + fn from(backend: T) -> Self { + Self(Some(backend)) + } +} + +impl From> for OptionalBackend { + fn from(backend: Option) -> Self { + Self(backend) + } +} + +impl Backend for OptionalBackend { + type Context = T::Context; + + fn request( + &mut self, + core_ctx: &mut CoreContext, + backend_ctx: &mut Self::Context, + request: &Request, + resources: &mut ServiceResources

, + ) -> Result { + self.inner()? + .request(core_ctx, backend_ctx, request, resources) + } +} diff --git a/src/serde_extensions.rs b/src/serde_extensions.rs index fa298269665..b70f264d9dd 100644 --- a/src/serde_extensions.rs +++ b/src/serde_extensions.rs @@ -17,7 +17,7 @@ use core::{marker::PhantomData, task::Poll}; use crate::{ api::{reply, request, Reply, Request}, - backend::{Backend, CoreOnly, Dispatch, NoId}, + backend::{Backend, CoreOnly, Dispatch, NoId, OptionalBackend}, client::{ClientError, ClientImplementation, FutureResult, PollClient}, error::Error, platform::{Platform, Syscall}, @@ -131,6 +131,19 @@ pub trait ExtensionImpl: Backend { } } +impl> ExtensionImpl for OptionalBackend { + fn extension_request( + &mut self, + core_ctx: &mut CoreContext, + backend_ctx: &mut Self::Context, + request: &E::Request, + resources: &mut ServiceResources

, + ) -> Result { + self.inner()? + .extension_request(core_ctx, backend_ctx, request, resources) + } +} + /// Provides access to the extension IDs assigned by the runner. pub trait ExtensionId { /// The ID type used by the runner.