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 eaeb7e2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
47 changes: 47 additions & 0 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,50 @@ 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>(pub Option<T>);

impl<T> OptionalBackend<T> {
/// 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)
}
}

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 eaeb7e2

Please sign in to comment.