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