imago/format/
wrapped.rs

1//! Allows using [`FormatAccess`] in containers.
2//!
3//! Users may want to wrap [`FormatAccess`] objects e.g. in `Arc` and then assign them as
4//! dependencies to other objects (e.g. as a backing image).  The [`WrappedFormat`] trait provided
5//! here allows images to use other images (`FormatAccess` objects) regardless of whether they are
6//! wrapped in such containers or not.
7
8use crate::{FormatAccess, Storage};
9use std::fmt::{Debug, Display};
10use std::ops::Deref;
11use std::sync::Arc;
12use tokio::sync::{OwnedRwLockReadGuard, RwLock};
13
14/// Represents [`FormatAccess`] wrapped in e.g. `Arc`, `Box`, or nothing at all.
15///
16/// This struct is necessary so that we can reference format instances regardless of whether the
17/// user decides to wrap them or not.
18pub trait WrappedFormat<S: Storage>: Debug + Display + Send + Sync {
19    /// Construct this `WrappedFormat`.
20    fn wrap(inner: FormatAccess<S>) -> Self;
21
22    /// Access the inner format instance.
23    fn inner(&self) -> &FormatAccess<S>;
24}
25
26impl<
27        S: Storage + 'static,
28        D: Deref<Target = FormatAccess<S>> + Debug + Display + From<FormatAccess<S>> + Send + Sync,
29    > WrappedFormat<S> for D
30{
31    fn wrap(inner: FormatAccess<S>) -> Self {
32        Self::from(inner)
33    }
34
35    fn inner(&self) -> &FormatAccess<S> {
36        self.deref()
37    }
38}
39
40impl<S: Storage> WrappedFormat<S> for FormatAccess<S> {
41    fn wrap(inner: FormatAccess<S>) -> Self {
42        inner
43    }
44
45    fn inner(&self) -> &FormatAccess<S> {
46        self
47    }
48}
49
50impl<S: Storage> WrappedFormat<S> for OwnedRwLockReadGuard<FormatAccess<S>> {
51    fn wrap(inner: FormatAccess<S>) -> Self {
52        // Ugly, but works.
53        Arc::new(RwLock::new(inner)).try_read_owned().unwrap()
54    }
55
56    fn inner(&self) -> &FormatAccess<S> {
57        self.deref()
58    }
59}