Skip to main content

vhdx/medium/
options.rs

1//! Medium open/create option builder state.
2
3use std::marker::PhantomData;
4use std::path::PathBuf;
5
6use super::{LogReplayPolicy, ParentResolver};
7use crate::types::Guid;
8
9pub trait Len {
10    /// Return the current byte length of the medium.
11    ///
12    /// # Errors
13    ///
14    /// Returns an error if the medium length cannot be queried.
15    fn len(&mut self) -> std::io::Result<u64>;
16
17    /// Return whether the medium length is zero.
18    ///
19    /// # Errors
20    ///
21    /// Returns an error if the medium length cannot be queried.
22    fn is_empty(&mut self) -> std::io::Result<bool> {
23        self.len().map(|len| len == 0)
24    }
25}
26
27pub trait SetLen: Len {
28    /// Set the byte length of the medium.
29    ///
30    /// # Errors
31    ///
32    /// Returns an error if the medium length cannot be changed.
33    fn set_len(&mut self, len: u64) -> std::io::Result<()>;
34}
35
36pub trait SyncData {
37    /// Flush buffered file data to stable storage when supported.
38    ///
39    /// # Errors
40    ///
41    /// Returns an error if synchronization fails.
42    fn sync_data(&mut self) -> std::io::Result<()>;
43}
44
45impl Len for std::fs::File {
46    fn len(&mut self) -> std::io::Result<u64> {
47        Ok(self.metadata()?.len())
48    }
49}
50
51impl SetLen for std::fs::File {
52    fn set_len(&mut self, len: u64) -> std::io::Result<()> {
53        std::fs::File::set_len(self, len)
54    }
55}
56
57impl SyncData for std::fs::File {
58    fn sync_data(&mut self) -> std::io::Result<()> {
59        std::fs::File::sync_data(self)
60    }
61}
62
63impl Len for std::io::Cursor<Vec<u8>> {
64    fn len(&mut self) -> std::io::Result<u64> {
65        u64::try_from(self.get_ref().len())
66            .map_err(|_| std::io::Error::other("cursor length does not fit u64"))
67    }
68}
69
70impl SetLen for std::io::Cursor<Vec<u8>> {
71    fn set_len(&mut self, len: u64) -> std::io::Result<()> {
72        let len = usize::try_from(len)
73            .map_err(|_| std::io::Error::other("cursor length does not fit usize"))?;
74        self.get_mut().resize(len, 0);
75        if self.position() > len as u64 {
76            self.set_position(len as u64);
77        }
78        Ok(())
79    }
80}
81
82impl SyncData for std::io::Cursor<Vec<u8>> {
83    fn sync_data(&mut self) -> std::io::Result<()> {
84        Ok(())
85    }
86}
87
88/// Builder for configuring how an existing VHDX file is opened.
89///
90/// Obtain via [`Medium::open`]. The default configuration is:
91/// - read-only (no write access)
92/// - strict validation enabled
93/// - log replay policy: [`LogReplayPolicy::Require`]
94///
95/// # Standard
96///
97/// docs/Standard/MS-VHDX-只读扩展标准.md §3/§4
98pub struct ReadOnly;
99
100pub struct ReadWrite;
101
102pub struct OpenOptions<T, Mode = ReadOnly> {
103    pub(super) inner: T,
104    pub(super) strict: bool,
105    pub(super) log_replay_policy: LogReplayPolicy,
106    pub(super) parent_resolver: Option<Box<dyn ParentResolver + Send>>,
107    pub(super) _mode: PhantomData<Mode>,
108}
109
110/// Builder for creating a new VHDX file.
111pub struct CreateOptions<T = std::fs::File> {
112    pub(super) inner: Option<T>,
113    pub(super) virtual_size: u64,
114    pub(super) fixed: bool,
115    pub(super) block_size: u32,
116    pub(super) logical_sector_size: u32,
117    pub(super) physical_sector_size: u32,
118    pub(super) parent: Option<ParentCreateInfo>,
119}
120
121pub(crate) struct ParentCreateInfo {
122    pub(super) relative_path: PathBuf,
123    pub(super) data_write_guid: Guid,
124}