Skip to main content

imago/
null.rs

1//! Null storage.
2//!
3//! Discard all written data, and return zeroes when read.
4
5use crate::io_buffers::{IoVector, IoVectorMut};
6use crate::storage::drivers::CommonStorageHelper;
7use crate::storage::PreallocateMode;
8use crate::Storage;
9use maybe_async::maybe_async;
10use std::fmt::{self, Display, Formatter};
11use std::io;
12use std::sync::atomic::{AtomicU64, Ordering};
13
14/// Null storage object.
15///
16/// Reading from this will always return zeroes, writing to it does nothing (except to potentially
17/// grow its virtual “file length”).
18#[derive(Debug)]
19pub struct Null {
20    /// Virtual “file length”.
21    size: AtomicU64,
22
23    /// Storage helper.
24    common_storage_helper: CommonStorageHelper,
25}
26
27impl Null {
28    /// Create a new null storage object with the given initial virtual size.
29    pub fn new(size: u64) -> Self {
30        Null {
31            size: size.into(),
32            common_storage_helper: Default::default(),
33        }
34    }
35}
36
37#[maybe_async(AFIT)]
38impl Storage for Null {
39    fn size(&self) -> io::Result<u64> {
40        Ok(self.size.load(Ordering::Relaxed))
41    }
42
43    async unsafe fn pure_readv(&self, mut bufv: IoVectorMut<'_>, _offset: u64) -> io::Result<()> {
44        bufv.fill(0);
45        Ok(())
46    }
47
48    async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
49        let Some(end) = offset.checked_add(bufv.len()) else {
50            return Err(io::Error::other("Write too long"));
51        };
52
53        self.size.fetch_max(end, Ordering::Relaxed);
54        Ok(())
55    }
56
57    async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
58        let Some(end) = offset.checked_add(length) else {
59            return Err(io::Error::other("Write too long"));
60        };
61
62        self.size.fetch_max(end, Ordering::Relaxed);
63        Ok(())
64    }
65
66    async fn flush(&self) -> io::Result<()> {
67        // Nothing to do, there are no buffers
68        Ok(())
69    }
70
71    async fn sync(&self) -> io::Result<()> {
72        // Nothing to do, there is no hardware
73        Ok(())
74    }
75
76    async unsafe fn invalidate_cache(&self) -> io::Result<()> {
77        // Nothing to do, there are no buffers
78        Ok(())
79    }
80
81    fn get_storage_helper(&self) -> &CommonStorageHelper {
82        &self.common_storage_helper
83    }
84
85    async fn resize(&self, new_size: u64, _prealloc_mode: PreallocateMode) -> io::Result<()> {
86        self.size.store(new_size, Ordering::Relaxed);
87        Ok(())
88    }
89}
90
91impl Display for Null {
92    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
93        write!(f, "null:[{}B]", self.size.load(Ordering::Relaxed))
94    }
95}