1use crate::format::builder::{
6 FormatCreateBuilder, FormatCreateBuilderBase, FormatDriverBuilder, FormatDriverBuilderBase,
7};
8use crate::format::drivers::FormatDriverInstance;
9use crate::format::gate::ImplicitOpenGate;
10use crate::format::{Format, PreallocateMode};
11use crate::{
12 storage, DenyImplicitOpenGate, ShallowMapping, Storage, StorageExt, StorageOpenOptions,
13};
14use async_trait::async_trait;
15use std::fmt::{self, Display, Formatter};
16use std::io;
17use std::path::{Path, PathBuf};
18use std::sync::atomic::{AtomicU64, Ordering};
19
20#[derive(Debug)]
22pub struct Raw<S: Storage + 'static> {
23 inner: S,
25
26 writable: bool,
28
29 size: AtomicU64,
31}
32
33impl<S: Storage + 'static> Raw<S> {
34 pub fn builder(image: S) -> RawOpenBuilder<S> {
36 RawOpenBuilder::new(image)
37 }
38
39 pub fn builder_path<P: AsRef<Path>>(image_path: P) -> RawOpenBuilder<S> {
41 RawOpenBuilder::new_path(image_path)
42 }
43
44 pub fn create_builder(image: S) -> RawCreateBuilder<S> {
46 RawCreateBuilder::new(image)
47 }
48
49 pub async fn open_image(inner: S, writable: bool) -> io::Result<Self> {
51 let size = inner.size()?;
52 Ok(Raw {
53 inner,
54 writable,
55 size: size.into(),
56 })
57 }
58
59 pub async fn open_path<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
61 let storage_opts = StorageOpenOptions::new().write(writable).filename(path);
62 let inner = S::open(storage_opts).await?;
63 Self::open_image(inner, writable).await
64 }
65
66 #[cfg(feature = "sync-wrappers")]
68 pub fn open_image_sync(inner: S, writable: bool) -> io::Result<Self> {
69 let size = inner.size()?;
70 Ok(Raw {
71 inner,
72 writable,
73 size: size.into(),
74 })
75 }
76
77 #[cfg(feature = "sync-wrappers")]
78 pub fn open_path_sync<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
80 tokio::runtime::Builder::new_current_thread()
81 .build()?
82 .block_on(Self::open_path(path, writable))
83 }
84}
85
86#[async_trait(?Send)]
87impl<S: Storage + 'static> FormatDriverInstance for Raw<S> {
88 type Storage = S;
89
90 fn format(&self) -> Format {
91 Format::Raw
92 }
93
94 async unsafe fn probe(_storage: &S) -> io::Result<bool>
95 where
96 Self: Sized,
97 {
98 Ok(true)
99 }
100
101 fn size(&self) -> u64 {
102 self.size.load(Ordering::Relaxed)
103 }
104
105 fn zero_granularity(&self) -> Option<u64> {
106 None
107 }
108
109 fn collect_storage_dependencies(&self) -> Vec<&S> {
110 vec![&self.inner]
111 }
112
113 fn writable(&self) -> bool {
114 self.writable
115 }
116
117 async fn get_mapping<'a>(
118 &'a self,
119 offset: u64,
120 max_length: u64,
121 ) -> io::Result<(ShallowMapping<'a, S>, u64)> {
122 let remaining = match self.size().checked_sub(offset) {
123 None | Some(0) => return Ok((ShallowMapping::Eof {}, 0)),
124 Some(remaining) => remaining,
125 };
126
127 Ok((
128 ShallowMapping::Raw {
129 storage: &self.inner,
130 offset,
131 writable: true,
132 },
133 std::cmp::min(max_length, remaining),
134 ))
135 }
136
137 async fn ensure_data_mapping<'a>(
138 &'a self,
139 offset: u64,
140 length: u64,
141 _overwrite: bool,
142 ) -> io::Result<(&'a S, u64, u64)> {
143 let Some(remaining) = self.size().checked_sub(offset) else {
144 return Err(io::Error::other("Cannot allocate past the end of file"));
145 };
146 if length > remaining {
147 return Err(io::Error::other("Cannot allocate past the end of file"));
148 }
149
150 Ok((&self.inner, offset, length))
151 }
152
153 async fn ensure_zero_mapping(&self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
154 let zero_align = self.inner.zero_align();
155 assert!(zero_align.is_power_of_two());
156
157 let zero_align_mask = zero_align as u64 - 1;
158
159 let aligned_end = (offset + length) & !zero_align_mask;
160 let aligned_offset = (offset + zero_align_mask) & !zero_align_mask;
161 let aligned_length = aligned_end.saturating_sub(aligned_offset);
162 if aligned_length == 0 {
163 return Ok((aligned_offset, 0));
164 }
165
166 self.inner
168 .write_zeroes(aligned_offset, aligned_length)
169 .await?;
170 Ok((aligned_offset, aligned_length))
171 }
172
173 async unsafe fn discard_to_zero_unsafe(
174 &self,
175 offset: u64,
176 length: u64,
177 ) -> io::Result<(u64, u64)> {
178 self.ensure_zero_mapping(offset, length).await
179 }
180
181 async unsafe fn discard_to_any_unsafe(
182 &self,
183 offset: u64,
184 length: u64,
185 ) -> io::Result<(u64, u64)> {
186 let discard_align = self.inner.discard_align();
187 assert!(discard_align.is_power_of_two());
188
189 let discard_align_mask = discard_align as u64 - 1;
190
191 let aligned_end = (offset + length) & !discard_align_mask;
192 let aligned_offset = (offset + discard_align_mask) & !discard_align_mask;
193 let aligned_length = aligned_end.saturating_sub(aligned_offset);
194 if aligned_length == 0 {
195 return Ok((aligned_offset, 0));
196 }
197
198 self.inner.discard(aligned_offset, aligned_length).await?;
199 Ok((aligned_offset, aligned_length))
200 }
201
202 async unsafe fn discard_to_backing_unsafe(
203 &self,
204 offset: u64,
205 length: u64,
206 ) -> io::Result<(u64, u64)> {
207 unsafe { self.discard_to_zero_unsafe(offset, length).await }
208 }
209
210 async fn flush(&self) -> io::Result<()> {
211 self.inner.flush().await
213 }
214
215 async fn sync(&self) -> io::Result<()> {
216 self.inner.sync().await
217 }
218
219 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
220 unsafe { self.inner.invalidate_cache() }.await
223 }
224
225 async fn resize_grow(
226 &self,
227 new_size: u64,
228 format_prealloc_mode: PreallocateMode,
229 ) -> io::Result<()> {
230 if self
231 .size
232 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| {
233 (new_size > old).then_some(new_size)
234 })
235 .is_err()
236 {
237 return Ok(()); }
239
240 let storage_prealloc_mode = match format_prealloc_mode {
241 PreallocateMode::None => storage::PreallocateMode::None,
242 PreallocateMode::Zero | PreallocateMode::FormatAllocate => {
243 storage::PreallocateMode::Zero
244 }
245 PreallocateMode::FullAllocate => storage::PreallocateMode::Allocate,
246 PreallocateMode::WriteData => storage::PreallocateMode::WriteData,
247 };
248 self.inner.resize(new_size, storage_prealloc_mode).await
249 }
250
251 async fn resize_shrink(&mut self, new_size: u64) -> io::Result<()> {
252 if self
253 .size
254 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| {
255 (new_size < old).then_some(new_size)
256 })
257 .is_err()
258 {
259 return Ok(()); }
261
262 self.inner
263 .resize(new_size, storage::PreallocateMode::None)
264 .await
265 }
266}
267
268impl<S: Storage + 'static> Display for Raw<S> {
269 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
270 write!(f, "raw[{}]", self.inner)
271 }
272}
273
274pub struct RawOpenBuilder<S: Storage + 'static>(FormatDriverBuilderBase<S>);
276
277impl<S: Storage + 'static> FormatDriverBuilder<S> for RawOpenBuilder<S> {
278 type Format = Raw<S>;
279 const FORMAT: Format = Format::Raw;
280
281 fn new(image: S) -> Self {
282 RawOpenBuilder(FormatDriverBuilderBase::new(image))
283 }
284
285 fn new_path<P: AsRef<Path>>(path: P) -> Self {
286 RawOpenBuilder(FormatDriverBuilderBase::new_path(path))
287 }
288
289 fn write(mut self, writable: bool) -> Self {
290 self.0.set_write(writable);
291 self
292 }
293
294 fn storage_open_options(mut self, options: StorageOpenOptions) -> Self {
295 self.0.set_storage_open_options(options);
296 self
297 }
298
299 async fn open<G: ImplicitOpenGate<S>>(self, mut gate: G) -> io::Result<Self::Format> {
300 let writable = self.0.get_writable();
301 let file = self.0.open_image(&mut gate).await?;
302 Raw::open_image(file, writable).await
303 }
304
305 fn get_image_path(&self) -> Option<PathBuf> {
306 self.0.get_image_path()
307 }
308
309 fn get_writable(&self) -> bool {
310 self.0.get_writable()
311 }
312
313 fn get_storage_open_options(&self) -> Option<&StorageOpenOptions> {
314 self.0.get_storage_opts()
315 }
316}
317
318pub struct RawCreateBuilder<S: Storage + 'static>(FormatCreateBuilderBase<S>);
320
321impl<S: Storage + 'static> FormatCreateBuilder<S> for RawCreateBuilder<S> {
322 const FORMAT: Format = Format::Raw;
323 type DriverBuilder = RawOpenBuilder<S>;
324
325 fn new(image: S) -> Self {
326 RawCreateBuilder(FormatCreateBuilderBase::new(image))
327 }
328
329 fn size(mut self, size: u64) -> Self {
330 self.0.set_size(size);
331 self
332 }
333
334 fn preallocate(mut self, prealloc_mode: PreallocateMode) -> Self {
335 self.0.set_preallocate(prealloc_mode);
336 self
337 }
338
339 fn get_size(&self) -> u64 {
340 self.0.get_size()
341 }
342
343 fn get_preallocate(&self) -> PreallocateMode {
344 self.0.get_preallocate()
345 }
346
347 async fn create(self) -> io::Result<()> {
348 self.create_open(DenyImplicitOpenGate::default(), |image| {
349 Ok(Raw::builder(image))
350 })
351 .await?;
352 Ok(())
353 }
354
355 async fn create_open<
356 G: ImplicitOpenGate<S>,
357 F: FnOnce(S) -> io::Result<Self::DriverBuilder>,
358 >(
359 self,
360 open_gate: G,
361 open_builder_fn: F,
362 ) -> io::Result<Raw<S>> {
363 let size = self.0.get_size();
364 let prealloc = self.0.get_preallocate();
365 let image = self.0.get_image();
366
367 if image.size()? > 0 {
369 image.resize(size, storage::PreallocateMode::None).await?;
370 }
371
372 let img = open_builder_fn(image)?.write(true).open(open_gate).await?;
373 if size > 0 {
374 img.resize_grow(size, prealloc).await?;
375 }
376
377 Ok(img)
378 }
379}