Skip to main content

guestmem/
ranges.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! [`GuestMemory`]-backed readers and writers for guest memory ranges.
5//!
6//! The core range descriptors — [`PagedRange`] and [`PagedRanges`] — live in
7//! [`guestmem_core::ranges`] so they can be used from `no_std` contexts. This
8//! module supplies the `std`-only bridge between those descriptors and
9//! [`GuestMemory`].
10
11pub use guestmem_core::ranges::PagedRange;
12pub use guestmem_core::ranges::PagedRanges;
13
14use super::AccessError;
15use super::GuestMemory;
16use super::MemoryRead;
17use super::MemoryWrite;
18
19/// Adapter trait attaching a [`GuestMemory`] backing to a range descriptor to
20/// produce byte-oriented readers and writers.
21///
22/// This trait is the extension point that lets [`PagedRange`] and
23/// [`PagedRanges`] — which by themselves are pure address-space descriptors
24/// with no attached memory — be read from or written to. It is implemented for
25/// both range types in this module and is not intended to be implemented by
26/// downstream crates.
27///
28/// The typical call pattern is:
29///
30/// ```ignore
31/// use guestmem::MemoryRead;
32/// use guestmem::ranges::GuestMemoryView;
33///
34/// let mut reader = range.reader(&mem);
35/// let value: MyStruct = reader.read_plain()?;
36/// ```
37pub trait GuestMemoryView<'a> {
38    /// The [`MemoryRead`] implementation type
39    type Reader: MemoryRead;
40
41    /// The [`MemoryWrite`] implementation type
42    type Writer: MemoryWrite;
43
44    /// Returns a [`MemoryRead`] implementation for the ranges.
45    fn reader(self, mem: &'a GuestMemory) -> Self::Reader;
46
47    /// Returns a [`MemoryWrite`] implementation for the ranges.
48    fn writer(self, mem: &'a GuestMemory) -> Self::Writer;
49}
50
51impl<'a, T: Iterator<Item = PagedRange<'a>>> GuestMemoryView<'a> for PagedRanges<'a, T> {
52    type Reader = PagedRangesReader<'a, T>;
53    type Writer = PagedRangesWriter<'a, T>;
54
55    fn reader(self, mem: &'a GuestMemory) -> Self::Reader {
56        PagedRangesReader { views: self, mem }
57    }
58
59    fn writer(self, mem: &'a GuestMemory) -> Self::Writer {
60        PagedRangesWriter { views: self, mem }
61    }
62}
63
64/// A [`MemoryRead`] implementation for [`PagedRanges`].
65#[derive(Debug, Clone)]
66pub struct PagedRangesReader<'a, T> {
67    views: PagedRanges<'a, T>,
68    mem: &'a GuestMemory,
69}
70
71impl<'a, T> PagedRangesReader<'a, T> {
72    /// Returns the inner ranges.
73    pub fn into_inner(self) -> PagedRanges<'a, T> {
74        self.views
75    }
76}
77
78impl<'a, T: Iterator<Item = PagedRange<'a>>> MemoryRead for PagedRangesReader<'a, T> {
79    fn read(&mut self, mut data: &mut [u8]) -> Result<&mut Self, AccessError> {
80        if self.len() < data.len() {
81            return Err(AccessError::OutOfRange(self.len(), data.len()));
82        }
83        while !data.is_empty() {
84            let range = self.views.current(data.len());
85            let (buf, rest) = data.split_at_mut(range.len());
86            self.mem
87                .read_range(&range, buf)
88                .map_err(AccessError::Memory)?;
89            self.views.advance(range.len());
90            data = rest;
91        }
92        Ok(self)
93    }
94
95    fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
96        if self.len() < len {
97            return Err(AccessError::OutOfRange(self.len(), len));
98        }
99        self.views.skip(len);
100        Ok(self)
101    }
102
103    fn len(&self) -> usize {
104        self.views.len()
105    }
106}
107
108impl<'a> GuestMemoryView<'a> for PagedRange<'a> {
109    type Reader = PagedRangeReader<'a>;
110
111    type Writer = PagedRangeWriter<'a>;
112
113    fn reader(self, mem: &'a GuestMemory) -> PagedRangeReader<'a> {
114        PagedRangeReader { range: self, mem }
115    }
116
117    fn writer(self, mem: &'a GuestMemory) -> PagedRangeWriter<'a> {
118        PagedRangeWriter { range: self, mem }
119    }
120}
121
122/// A [`MemoryRead`] implementation for [`PagedRange`].
123pub struct PagedRangeReader<'a> {
124    range: PagedRange<'a>,
125    mem: &'a GuestMemory,
126}
127
128impl MemoryRead for PagedRangeReader<'_> {
129    fn read(&mut self, data: &mut [u8]) -> Result<&mut Self, AccessError> {
130        let range = self
131            .range
132            .try_subrange(0, data.len())
133            .ok_or_else(|| AccessError::OutOfRange(self.len(), data.len()))?;
134        self.mem
135            .read_range(&range, data)
136            .map_err(AccessError::Memory)?;
137        self.range.skip(data.len());
138        Ok(self)
139    }
140
141    fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
142        if self.len() < len {
143            return Err(AccessError::OutOfRange(self.len(), len));
144        }
145        self.range.skip(len);
146        Ok(self)
147    }
148
149    fn len(&self) -> usize {
150        self.range.len()
151    }
152}
153
154/// A [`MemoryWrite`] implementation for [`PagedRange`].
155pub struct PagedRangeWriter<'a> {
156    range: PagedRange<'a>,
157    mem: &'a GuestMemory,
158}
159
160impl MemoryWrite for PagedRangeWriter<'_> {
161    fn write(&mut self, data: &[u8]) -> Result<(), AccessError> {
162        let range = self
163            .range
164            .try_subrange(0, data.len())
165            .ok_or_else(|| AccessError::OutOfRange(self.len(), data.len()))?;
166        self.mem
167            .write_range(&range, data)
168            .map_err(AccessError::Memory)?;
169        self.range.skip(data.len());
170        Ok(())
171    }
172
173    fn fill(&mut self, val: u8, len: usize) -> Result<(), AccessError> {
174        let range = self
175            .range
176            .try_subrange(0, len)
177            .ok_or_else(|| AccessError::OutOfRange(self.len(), len))?;
178        self.mem
179            .fill_range(&range, val)
180            .map_err(AccessError::Memory)?;
181        self.range.skip(len);
182        Ok(())
183    }
184
185    fn len(&self) -> usize {
186        self.range.len()
187    }
188}
189
190/// A [`MemoryWrite`] implementation for [`PagedRanges`].
191#[derive(Debug)]
192pub struct PagedRangesWriter<'a, T> {
193    views: PagedRanges<'a, T>,
194    mem: &'a GuestMemory,
195}
196
197impl<'a, T> PagedRangesWriter<'a, T> {
198    /// Returns the inner ranges.
199    pub fn into_inner(self) -> PagedRanges<'a, T> {
200        self.views
201    }
202}
203
204impl<'a, T: Iterator<Item = PagedRange<'a>>> MemoryWrite for PagedRangesWriter<'a, T> {
205    fn write(&mut self, mut data: &[u8]) -> Result<(), AccessError> {
206        if self.len() < data.len() {
207            return Err(AccessError::OutOfRange(self.len(), data.len()));
208        }
209        while !data.is_empty() {
210            let range = self.views.current(data.len());
211            let (buf, rest) = data.split_at(range.len());
212            self.mem
213                .write_range(&range, buf)
214                .map_err(AccessError::Memory)?;
215            self.views.advance(range.len());
216            data = rest;
217        }
218        Ok(())
219    }
220
221    fn fill(&mut self, val: u8, mut len: usize) -> Result<(), AccessError> {
222        if self.len() < len {
223            return Err(AccessError::OutOfRange(self.len(), len));
224        }
225        while len > 0 {
226            let range = self.views.current(len);
227            self.mem
228                .fill_range(&range, val)
229                .map_err(AccessError::Memory)?;
230            self.views.advance(range.len());
231            len -= range.len();
232        }
233        Ok(())
234    }
235
236    fn len(&self) -> usize {
237        self.views.len()
238    }
239}