Skip to main content

vfsi_core/api/
write.rs

1//! Portable borrowed positional writes.
2use crate::api::FileHandle;
3
4#[bitfields::bitfield(u8)]
5#[derive(PartialEq, Eq)]
6struct WriteFlags {
7    write_all: bool,
8    #[bits(7)]
9    _reserved: u8,
10}
11
12/// Policy for positional vector writes. Defaults to reporting short writes.
13/// Completion is not atomicity, durability, or permission to replay failed RPCs.
14#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
15pub struct WriteOptions {
16    flags: WriteFlags,
17}
18impl WriteOptions {
19    /// Report each request's accepted byte count without completing short writes.
20    pub const fn new() -> Self {
21        Self {
22            flags: WriteFlags::new(),
23        }
24    }
25    /// Complete successful short writes at their remaining offsets when true.
26    /// Stop on any error, including ambiguous transport failures; never replay it.
27    /// This does not flush data to stable storage or make the batch atomic.
28    pub const fn write_all(mut self, complete: bool) -> Self {
29        self.flags.set_write_all(complete);
30        self
31    }
32    /// Whether successful short writes should be completed.
33    pub const fn writes_all(self) -> bool {
34        self.flags.write_all()
35    }
36}
37
38/// A positional write borrowing its handle and payload without copying either.
39/// Construction performs no I/O or allocation. Does not change the file cursor.
40pub struct WriteOp<'a, H: FileHandle + 'a> {
41    file: &'a H,
42    offset: u64,
43    data: &'a [u8],
44}
45impl<H: FileHandle> Copy for WriteOp<'_, H> {}
46impl<H: FileHandle> Clone for WriteOp<'_, H> {
47    fn clone(&self) -> Self {
48        *self
49    }
50}
51impl<H: FileHandle> std::fmt::Debug for WriteOp<'_, H> {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        f.debug_struct("WriteOp")
54            .field("offset", &self.offset)
55            .field("length", &self.data.len())
56            .finish_non_exhaustive()
57    }
58}
59impl<'a, H: FileHandle> WriteOp<'a, H> {
60    /// Prepare a write at an absolute byte offset; validation happens at dispatch.
61    ///
62    /// ```no_run
63    /// use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
64    /// # fn example(fs: &impl Vfsi) -> vfsi_core::api::Result<()> {
65    /// let file = fs.create("/output")?;
66    /// let result = fs.vwrite(&[WriteOp::at(&file, 0, b"hello")], vfsi_core::api::WriteOptions::new().write_all(true));
67    /// let close = fs.close_files(vec![file]);
68    /// result?;
69    /// close?;
70    /// # Ok(())
71    /// # }
72    /// ```
73    pub fn at(file: &'a H, offset: u64, data: &'a [u8]) -> Self {
74        Self { file, offset, data }
75    }
76    /// The borrowed handle, available to third-party client implementations.
77    pub fn file(&self) -> &'a H {
78        self.file
79    }
80    /// Absolute byte offset, independent of the handle's cursor.
81    pub fn offset(&self) -> u64 {
82        self.offset
83    }
84    /// Borrowed payload; no ownership transfer or copy occurs.
85    pub fn data(&self) -> &'a [u8] {
86        self.data
87    }
88}
89
90#[cfg(test)]
91mod option_layout_tests {
92    use super::*;
93    #[test]
94    fn packed_completion_flag_keeps_const_defaults_and_toggles() {
95        const COMPLETE: WriteOptions = WriteOptions::new().write_all(true);
96        assert_eq!(std::mem::size_of::<WriteOptions>(), 1);
97        assert!(!WriteOptions::default().writes_all());
98        assert!(COMPLETE.writes_all());
99        assert!(!COMPLETE.write_all(false).writes_all());
100        assert!(COMPLETE.write_all(false).write_all(true).writes_all());
101    }
102}