Skip to main content

virtio_accel_transport/
bytes.rs

1//! Transport-owned byte access that is independent of backend error semantics.
2
3use core::fmt;
4
5/// Failure while accessing a validated transport byte region.
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum ByteAccessError {
8    /// The requested logical range is outside the mapped region.
9    OutOfBounds,
10    /// Another live access currently owns the same bytes.
11    Busy,
12    /// Queue reset invalidated the region before access.
13    Reset,
14    /// The concrete transport can no longer access the mapped memory.
15    Access,
16}
17
18/// Bounded readable bytes exposed by a transport implementation.
19///
20/// Implementations may be segmented. Every operation is nonblocking and allocation-free.
21pub trait ReadableBytes: fmt::Debug {
22    /// Stable logical byte length.
23    fn len(&self) -> u64;
24
25    /// Whether this source contains no bytes.
26    fn is_empty(&self) -> bool {
27        self.len() == 0
28    }
29
30    /// Fill `target` from the exact logical range beginning at `offset`.
31    fn read_at(&self, offset: u64, target: &mut [u8]) -> Result<(), ByteAccessError>;
32
33    /// Borrow the complete source when the concrete mapping is contiguous and stable.
34    fn as_contiguous(&self) -> Option<&[u8]> {
35        None
36    }
37}
38
39/// Bounded writable bytes exposed by a transport implementation.
40///
41/// Implementations may be segmented. Every operation is nonblocking and allocation-free.
42pub trait WritableBytes: fmt::Debug {
43    /// Stable logical byte length.
44    fn len(&self) -> u64;
45
46    /// Whether this destination contains no bytes.
47    fn is_empty(&self) -> bool {
48        self.len() == 0
49    }
50
51    /// Write `source` to the exact logical range beginning at `offset`.
52    fn write_at(&mut self, offset: u64, source: &[u8]) -> Result<(), ByteAccessError>;
53
54    /// Borrow the complete destination when the concrete mapping is contiguous and stable.
55    fn as_contiguous_mut(&mut self) -> Option<&mut [u8]> {
56        None
57    }
58}
59
60/// Driver-owned byte access for one unpublished or reclaimed descriptor chain.
61///
62/// The readable side is written by the driver and later read by the device. The writable side is
63/// written by the device and may be read by the driver only after used-ring reclamation. Methods
64/// are nonblocking and allocation-free; queue ownership prevents calls while a chain is published.
65pub trait DriverChainBuffer: fmt::Debug {
66    /// Concrete transport byte-access failure.
67    type Error;
68
69    /// Total bytes readable by the device.
70    fn device_readable_len(&self) -> u64;
71
72    /// Total bytes writable by the device.
73    fn device_writable_len(&self) -> u64;
74
75    /// Write an exact logical range into the device-readable side.
76    fn write_device_readable(&mut self, offset: u64, source: &[u8]) -> Result<(), Self::Error>;
77
78    /// Read an exact logical range from the device-writable side after completion.
79    fn read_device_writable(&self, offset: u64, target: &mut [u8]) -> Result<(), Self::Error>;
80}
81
82impl ReadableBytes for [u8] {
83    fn len(&self) -> u64 {
84        self.len() as u64
85    }
86
87    fn read_at(&self, offset: u64, target: &mut [u8]) -> Result<(), ByteAccessError> {
88        let start = usize::try_from(offset).map_err(|_| ByteAccessError::OutOfBounds)?;
89        let end = start
90            .checked_add(target.len())
91            .ok_or(ByteAccessError::OutOfBounds)?;
92        let source = self.get(start..end).ok_or(ByteAccessError::OutOfBounds)?;
93        target.copy_from_slice(source);
94        Ok(())
95    }
96
97    fn as_contiguous(&self) -> Option<&[u8]> {
98        Some(self)
99    }
100}
101
102impl WritableBytes for [u8] {
103    fn len(&self) -> u64 {
104        self.len() as u64
105    }
106
107    fn write_at(&mut self, offset: u64, source: &[u8]) -> Result<(), ByteAccessError> {
108        let start = usize::try_from(offset).map_err(|_| ByteAccessError::OutOfBounds)?;
109        let end = start
110            .checked_add(source.len())
111            .ok_or(ByteAccessError::OutOfBounds)?;
112        let target = self
113            .get_mut(start..end)
114            .ok_or(ByteAccessError::OutOfBounds)?;
115        target.copy_from_slice(source);
116        Ok(())
117    }
118
119    fn as_contiguous_mut(&mut self) -> Option<&mut [u8]> {
120        Some(self)
121    }
122}