imago/
annotated.rs

1//! Annotating wrapper around storage objects.
2//!
3//! Wraps other storage objects, adding an arbitrary tag to them.
4//!
5//! This may be useful when using the “mapping” interface, to identify the storage objects returned
6//! in raw mappings.
7//!
8//! Example:
9//! ```
10//! # use imago::{FormatAccess, Mapping};
11//! # use imago::annotated::Annotated;
12//! # use imago::null::Null;
13//! # use imago::raw::Raw;
14//! # tokio::runtime::Builder::new_current_thread()
15//! #   .build()
16//! #   .unwrap()
17//! #   .block_on(async move {
18//! #
19//! const TEST_TAG: u32 = 42;
20//!
21//! let disk_size = 16 << 30;
22//! let test_offset = 1 << 30;
23//!
24//! let inner_storage = Null::new(disk_size);
25//! let annotated_storage = Annotated::new(inner_storage, TEST_TAG);
26//! let image = Raw::open_image(annotated_storage, false).await?;
27//! let image = FormatAccess::new(image);
28//!
29//! let mapping = image.get_mapping(test_offset, 1).await?.0;
30//! let Mapping::Raw {
31//!     storage, offset, ..
32//! } = mapping
33//! else {
34//!     panic!("Raw mapping expected");
35//! };
36//! assert_eq!(*storage.tag(), TEST_TAG);
37//! assert_eq!(offset, test_offset);
38//! #
39//! # Ok::<(), std::io::Error>(())
40//! # }).unwrap()
41//! ```
42
43use crate::io_buffers::{IoVector, IoVectorMut};
44use crate::storage::drivers::CommonStorageHelper;
45use crate::storage::PreallocateMode;
46use crate::{Storage, StorageCreateOptions, StorageOpenOptions};
47use std::fmt::{self, Debug, Display, Formatter};
48use std::io;
49use std::ops::{Deref, DerefMut};
50use std::path::{Path, PathBuf};
51
52/// Annotating wrapper around storage objects.
53///
54/// Wraps other storage objects, adding an arbitrary tag to them.
55// TODO: Remove the `Default` requirement.  We want to implement `Storage::open()` if `Default` is
56// implemented, though, but return an error if it is not.  Doing that probably requires
57// specialization, though.
58#[derive(Debug)]
59pub struct Annotated<Tag: Debug + Default + Display + Send + Sync, S: Storage> {
60    /// Wrapped storage object.
61    inner: S,
62
63    /// Tag.
64    tag: Tag,
65}
66
67impl<T: Debug + Default + Display + Send + Sync, S: Storage> Annotated<T, S> {
68    /// Wrap `storage`, adding the tag `tag`.
69    pub fn new(storage: S, tag: T) -> Self {
70        Annotated {
71            inner: storage,
72            tag,
73        }
74    }
75
76    /// Get the tag.
77    pub fn tag(&self) -> &T {
78        &self.tag
79    }
80
81    /// Allow modifying or changing the tag.
82    pub fn tag_mut(&mut self) -> &mut T {
83        &mut self.tag
84    }
85}
86
87impl<T: Debug + Default + Display + Send + Sync, S: Storage> From<S> for Annotated<T, S> {
88    fn from(storage: S) -> Self {
89        Self::new(storage, T::default())
90    }
91}
92
93impl<T: Debug + Default + Display + Send + Sync, S: Storage> Storage for Annotated<T, S> {
94    async fn open(opts: StorageOpenOptions) -> io::Result<Self> {
95        Ok(S::open(opts).await?.into())
96    }
97
98    #[cfg(feature = "sync-wrappers")]
99    fn open_sync(opts: StorageOpenOptions) -> io::Result<Self> {
100        Ok(S::open_sync(opts)?.into())
101    }
102
103    async fn create_open(opts: StorageCreateOptions) -> io::Result<Self> {
104        Ok(S::create_open(opts).await?.into())
105    }
106
107    fn mem_align(&self) -> usize {
108        self.inner.mem_align()
109    }
110
111    fn req_align(&self) -> usize {
112        self.inner.req_align()
113    }
114
115    fn size(&self) -> io::Result<u64> {
116        self.inner.size()
117    }
118
119    fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
120        self.inner.resolve_relative_path(relative)
121    }
122
123    fn get_filename(&self) -> Option<PathBuf> {
124        self.inner.get_filename()
125    }
126
127    async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
128        // Caller guarantees safety
129        unsafe { self.inner.pure_readv(bufv, offset) }.await
130    }
131
132    async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
133        // Caller guarantees safety
134        unsafe { self.inner.pure_writev(bufv, offset) }.await
135    }
136
137    async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
138        // Caller guarantees safety
139        unsafe { self.inner.pure_write_zeroes(offset, length) }.await
140    }
141
142    async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
143        // Caller guarantees safety
144        unsafe { self.inner.pure_discard(offset, length) }.await
145    }
146
147    async fn flush(&self) -> io::Result<()> {
148        self.inner.flush().await
149    }
150
151    async fn sync(&self) -> io::Result<()> {
152        self.inner.sync().await
153    }
154
155    async unsafe fn invalidate_cache(&self) -> io::Result<()> {
156        // Safety ensured by caller
157        unsafe { self.inner.invalidate_cache() }.await
158    }
159
160    fn get_storage_helper(&self) -> &CommonStorageHelper {
161        // Share storage helper from inner (to e.g. get same request serialization)
162        self.inner.get_storage_helper()
163    }
164
165    async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
166        self.inner.resize(new_size, prealloc_mode).await
167    }
168}
169
170impl<T: Debug + Default + Display + Send + Sync, S: Storage> Deref for Annotated<T, S> {
171    type Target = S;
172
173    fn deref(&self) -> &S {
174        &self.inner
175    }
176}
177
178impl<T: Debug + Default + Display + Send + Sync, S: Storage> DerefMut for Annotated<T, S> {
179    fn deref_mut(&mut self) -> &mut S {
180        &mut self.inner
181    }
182}
183
184impl<T: Debug + Default + Display + Send + Sync, S: Storage> Display for Annotated<T, S> {
185    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
186        write!(f, "annotated({})[{}]", self.tag, self.inner)
187    }
188}