Skip to content

Commit

Permalink
Add OptionalBackend wrapper
Browse files Browse the repository at this point in the history
Backends can be activated at runtime depending on the configuration or
execution environment.  This patch adds an OptionalBackend wrapper that
implements Backend and ExtensionImpl but returns a RequestNotAvailable
error if the inner backend is not set.
  • Loading branch information
robin-nitrokey committed Apr 2, 2024
1 parent b548d37 commit 667d60c
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
57 changes: 57 additions & 0 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,60 @@ impl TryFrom<u8> for NoId {
Err(Error::InternalError)
}
}

/// Helper type for optional backends.
///
/// If the backend is `None`, [`Error::RequestNotAvailable`][] is returned.
#[derive(Debug)]
pub struct OptionalBackend<T>(Option<T>);

impl<T> OptionalBackend<T> {
/// Crates a new optional backend from an `Option<T>`.
pub fn new(backend: Option<T>) -> 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<T> {
self.0
}
}

impl<T> Default for OptionalBackend<T> {
fn default() -> Self {
Self(None)
}
}

impl<T> From<T> for OptionalBackend<T> {
fn from(backend: T) -> Self {
Self(Some(backend))
}
}

impl<T> From<Option<T>> for OptionalBackend<T> {
fn from(backend: Option<T>) -> Self {
Self(backend)
}
}

impl<T: Backend> Backend for OptionalBackend<T> {
type Context = T::Context;

fn request<P: Platform>(
&mut self,
core_ctx: &mut CoreContext,
backend_ctx: &mut Self::Context,
request: &Request,
resources: &mut ServiceResources<P>,
) -> Result<Reply, Error> {
self.inner()?
.request(core_ctx, backend_ctx, request, resources)
}
}
15 changes: 14 additions & 1 deletion src/serde_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -131,6 +131,19 @@ pub trait ExtensionImpl<E: Extension>: Backend {
}
}

impl<E: Extension, I: ExtensionImpl<E>> ExtensionImpl<E> for OptionalBackend<I> {
fn extension_request<P: Platform>(
&mut self,
core_ctx: &mut CoreContext,
backend_ctx: &mut Self::Context,
request: &E::Request,
resources: &mut ServiceResources<P>,
) -> Result<E::Reply, Error> {
self.inner()?
.extension_request(core_ctx, backend_ctx, request, resources)
}
}

/// Provides access to the extension IDs assigned by the runner.
pub trait ExtensionId<E> {
/// The ID type used by the runner.
Expand Down

0 comments on commit 667d60c

Please sign in to comment.