Skip to main content

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