Skip to main content

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;
11#[cfg(feature = "async")]
12use std::sync::Arc;
13#[cfg(feature = "async")]
14use tokio::sync::{OwnedRwLockReadGuard, RwLock};
15
16/// Represents [`FormatAccess`] wrapped in e.g. `Arc`, `Box`, or nothing at all.
17///
18/// This struct is necessary so that we can reference format instances regardless of whether the
19/// user decides to wrap them or not.
20pub trait WrappedFormat<S: Storage>: Debug + Display + Send + Sync {
21    /// Construct this `WrappedFormat`.
22    fn wrap(inner: FormatAccess<S>) -> Self;
23
24    /// Access the inner format instance.
25    fn inner(&self) -> &FormatAccess<S>;
26}
27
28impl<
29        S: Storage + 'static,
30        D: Deref<Target = FormatAccess<S>> + Debug + Display + From<FormatAccess<S>> + Send + Sync,
31    > WrappedFormat<S> for D
32{
33    fn wrap(inner: FormatAccess<S>) -> Self {
34        Self::from(inner)
35    }
36
37    fn inner(&self) -> &FormatAccess<S> {
38        self.deref()
39    }
40}
41
42impl<S: Storage> WrappedFormat<S> for FormatAccess<S> {
43    fn wrap(inner: FormatAccess<S>) -> Self {
44        inner
45    }
46
47    fn inner(&self) -> &FormatAccess<S> {
48        self
49    }
50}
51
52#[cfg(feature = "async")]
53impl<S: Storage> WrappedFormat<S> for OwnedRwLockReadGuard<FormatAccess<S>> {
54    fn wrap(inner: FormatAccess<S>) -> Self {
55        // Ugly, but works.
56        Arc::new(RwLock::new(inner)).try_read_owned().unwrap()
57    }
58
59    fn inner(&self) -> &FormatAccess<S> {
60        self.deref()
61    }
62}