xref: /aosp_15_r20/external/crosvm/cros_async/src/mem.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use base::VolatileSlice;
6*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
7*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
10*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
11*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
12*bb4ee6a4SAndroid Build Coastguard Worker     /// Invalid offset or length given for an iovec in backing memory.
13*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Invalid offset/len for getting a slice from {0} with len {1}.")]
14*bb4ee6a4SAndroid Build Coastguard Worker     InvalidOffset(u64, usize),
15*bb4ee6a4SAndroid Build Coastguard Worker }
16*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker /// Used to index subslices of backing memory. Like an iovec, but relative to the start of the
19*bb4ee6a4SAndroid Build Coastguard Worker /// backing memory instead of an absolute pointer.
20*bb4ee6a4SAndroid Build Coastguard Worker /// The backing memory referenced by the region can be an array, an mmapped file, or guest memory.
21*bb4ee6a4SAndroid Build Coastguard Worker /// The offset is a u64 to allow having file or guest offsets >4GB when run on a 32bit host.
22*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq)]
23*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemRegion {
24*bb4ee6a4SAndroid Build Coastguard Worker     pub offset: u64,
25*bb4ee6a4SAndroid Build Coastguard Worker     pub len: usize,
26*bb4ee6a4SAndroid Build Coastguard Worker }
27*bb4ee6a4SAndroid Build Coastguard Worker 
28*bb4ee6a4SAndroid Build Coastguard Worker /// Iterator over an ordered list of [`MemRegion`].
29*bb4ee6a4SAndroid Build Coastguard Worker ///
30*bb4ee6a4SAndroid Build Coastguard Worker /// In addition to the usual iterator operations, `MemRegionIter` provides extra functionality that
31*bb4ee6a4SAndroid Build Coastguard Worker /// allows subslicing individual memory regions without mutating the underlying list:
32*bb4ee6a4SAndroid Build Coastguard Worker /// - [`skip_bytes()`](Self::skip_bytes): Advance the iterator some number of bytes, potentially
33*bb4ee6a4SAndroid Build Coastguard Worker ///   starting iteration in the middle of a `MemRegion`.
34*bb4ee6a4SAndroid Build Coastguard Worker /// - [`take_bytes()`](Self::take_bytes): Truncate the iterator at some number of bytes, potentially
35*bb4ee6a4SAndroid Build Coastguard Worker ///   ending iteration in the middle of a `MemRegion`.
36*bb4ee6a4SAndroid Build Coastguard Worker ///
37*bb4ee6a4SAndroid Build Coastguard Worker /// The order of subslicing operations matters - limiting length followed by skipping bytes is not
38*bb4ee6a4SAndroid Build Coastguard Worker /// the same as skipping bytes followed by limiting length.
39*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
40*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemRegionIter<'a> {
41*bb4ee6a4SAndroid Build Coastguard Worker     regions: &'a [MemRegion],
42*bb4ee6a4SAndroid Build Coastguard Worker     skip_bytes: usize,
43*bb4ee6a4SAndroid Build Coastguard Worker     remaining_bytes: usize,
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker 
46*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> MemRegionIter<'a> {
47*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new `MemRegion` iterator over a slice of `MemRegion`.
48*bb4ee6a4SAndroid Build Coastguard Worker     ///
49*bb4ee6a4SAndroid Build Coastguard Worker     /// By default, the `MemRegionIter` will iterate over each `MemRegion` in the list in its
50*bb4ee6a4SAndroid Build Coastguard Worker     /// entirety. Call [`skip_bytes()`](Self::skip_bytes) and/or
51*bb4ee6a4SAndroid Build Coastguard Worker     /// [`take_bytes()`](Self::take_bytes) to limit iteration to a sub-slice of the specified
52*bb4ee6a4SAndroid Build Coastguard Worker     /// `regions` list.
new(regions: &'a [MemRegion]) -> Self53*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(regions: &'a [MemRegion]) -> Self {
54*bb4ee6a4SAndroid Build Coastguard Worker         MemRegionIter {
55*bb4ee6a4SAndroid Build Coastguard Worker             regions,
56*bb4ee6a4SAndroid Build Coastguard Worker             skip_bytes: 0,
57*bb4ee6a4SAndroid Build Coastguard Worker             remaining_bytes: usize::MAX,
58*bb4ee6a4SAndroid Build Coastguard Worker         }
59*bb4ee6a4SAndroid Build Coastguard Worker     }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker     /// Advance the iterator by `offset` bytes.
62*bb4ee6a4SAndroid Build Coastguard Worker     ///
63*bb4ee6a4SAndroid Build Coastguard Worker     /// This may place the iterator in the middle of a [`MemRegion`]; in this case, the offset and
64*bb4ee6a4SAndroid Build Coastguard Worker     /// length of the next [`MemRegion`] returned by [`next()`](Self::next) will be adjusted to
65*bb4ee6a4SAndroid Build Coastguard Worker     /// account for the offset.
66*bb4ee6a4SAndroid Build Coastguard Worker     ///
67*bb4ee6a4SAndroid Build Coastguard Worker     /// Skipping more than the remaining length of an iterator is not an error; if `offset` is
68*bb4ee6a4SAndroid Build Coastguard Worker     /// greater than or equal to the total number of remaining bytes, future calls to
69*bb4ee6a4SAndroid Build Coastguard Worker     /// [`next()`](Self::next) will simply return `None`.
skip_bytes(self, offset: usize) -> Self70*bb4ee6a4SAndroid Build Coastguard Worker     pub fn skip_bytes(self, offset: usize) -> Self {
71*bb4ee6a4SAndroid Build Coastguard Worker         MemRegionIter {
72*bb4ee6a4SAndroid Build Coastguard Worker             regions: self.regions,
73*bb4ee6a4SAndroid Build Coastguard Worker             skip_bytes: self.skip_bytes.saturating_add(offset),
74*bb4ee6a4SAndroid Build Coastguard Worker             remaining_bytes: self.remaining_bytes.saturating_sub(offset),
75*bb4ee6a4SAndroid Build Coastguard Worker         }
76*bb4ee6a4SAndroid Build Coastguard Worker     }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker     /// Truncate the length of the iterator to `max` bytes at most.
79*bb4ee6a4SAndroid Build Coastguard Worker     ///
80*bb4ee6a4SAndroid Build Coastguard Worker     /// This may cause the final [`MemRegion`] returned by [`next()`](Self::next) to be adjusted so
81*bb4ee6a4SAndroid Build Coastguard Worker     /// that its length does not cause the total number of bytes to exceed the requested `max`.
82*bb4ee6a4SAndroid Build Coastguard Worker     ///
83*bb4ee6a4SAndroid Build Coastguard Worker     /// If less than `max` bytes remain in the iterator already, this function will have no effect.
84*bb4ee6a4SAndroid Build Coastguard Worker     ///
85*bb4ee6a4SAndroid Build Coastguard Worker     /// Only truncation is supported; an iterator cannot be extended, even if it was truncated by a
86*bb4ee6a4SAndroid Build Coastguard Worker     /// previous call to `take_bytes()`.
take_bytes(self, max: usize) -> Self87*bb4ee6a4SAndroid Build Coastguard Worker     pub fn take_bytes(self, max: usize) -> Self {
88*bb4ee6a4SAndroid Build Coastguard Worker         MemRegionIter {
89*bb4ee6a4SAndroid Build Coastguard Worker             regions: self.regions,
90*bb4ee6a4SAndroid Build Coastguard Worker             skip_bytes: self.skip_bytes,
91*bb4ee6a4SAndroid Build Coastguard Worker             remaining_bytes: self.remaining_bytes.min(max),
92*bb4ee6a4SAndroid Build Coastguard Worker         }
93*bb4ee6a4SAndroid Build Coastguard Worker     }
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker impl Iterator for MemRegionIter<'_> {
97*bb4ee6a4SAndroid Build Coastguard Worker     type Item = MemRegion;
98*bb4ee6a4SAndroid Build Coastguard Worker 
next(&mut self) -> Option<Self::Item>99*bb4ee6a4SAndroid Build Coastguard Worker     fn next(&mut self) -> Option<Self::Item> {
100*bb4ee6a4SAndroid Build Coastguard Worker         if self.remaining_bytes == 0 {
101*bb4ee6a4SAndroid Build Coastguard Worker             return None;
102*bb4ee6a4SAndroid Build Coastguard Worker         }
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker         while let Some((first, remaining)) = self.regions.split_first() {
105*bb4ee6a4SAndroid Build Coastguard Worker             // This call to `next()` will consume `first`; future calls will start with `remaining`.
106*bb4ee6a4SAndroid Build Coastguard Worker             self.regions = remaining;
107*bb4ee6a4SAndroid Build Coastguard Worker 
108*bb4ee6a4SAndroid Build Coastguard Worker             // If skip_bytes encompasses this entire region, skip to the next region.
109*bb4ee6a4SAndroid Build Coastguard Worker             // This also skips zero-length regions, which should not be returned by the iterator.
110*bb4ee6a4SAndroid Build Coastguard Worker             if self.skip_bytes >= first.len {
111*bb4ee6a4SAndroid Build Coastguard Worker                 self.skip_bytes -= first.len;
112*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
113*bb4ee6a4SAndroid Build Coastguard Worker             }
114*bb4ee6a4SAndroid Build Coastguard Worker 
115*bb4ee6a4SAndroid Build Coastguard Worker             // Adjust the current region and reset `self.skip_bytes` to 0 to fully consume it.
116*bb4ee6a4SAndroid Build Coastguard Worker             let mut region = MemRegion {
117*bb4ee6a4SAndroid Build Coastguard Worker                 offset: first.offset + self.skip_bytes as u64,
118*bb4ee6a4SAndroid Build Coastguard Worker                 len: first.len - self.skip_bytes,
119*bb4ee6a4SAndroid Build Coastguard Worker             };
120*bb4ee6a4SAndroid Build Coastguard Worker             self.skip_bytes = 0;
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker             // If this region is at least as large as `remaining_bytes`, truncate the region and set
123*bb4ee6a4SAndroid Build Coastguard Worker             // `regions` to an empty slice to terminate iteration in future calls to `next()`.
124*bb4ee6a4SAndroid Build Coastguard Worker             if region.len >= self.remaining_bytes {
125*bb4ee6a4SAndroid Build Coastguard Worker                 region.len = self.remaining_bytes;
126*bb4ee6a4SAndroid Build Coastguard Worker                 self.remaining_bytes = 0;
127*bb4ee6a4SAndroid Build Coastguard Worker                 self.regions = &[];
128*bb4ee6a4SAndroid Build Coastguard Worker             } else {
129*bb4ee6a4SAndroid Build Coastguard Worker                 // Consume and return the full region.
130*bb4ee6a4SAndroid Build Coastguard Worker                 self.remaining_bytes -= region.len;
131*bb4ee6a4SAndroid Build Coastguard Worker             }
132*bb4ee6a4SAndroid Build Coastguard Worker 
133*bb4ee6a4SAndroid Build Coastguard Worker             // This should never return a zero-length region (should be handled by the
134*bb4ee6a4SAndroid Build Coastguard Worker             // `remaining_bytes == 0` early return and zero-length region skipping above).
135*bb4ee6a4SAndroid Build Coastguard Worker             debug_assert_ne!(region.len, 0);
136*bb4ee6a4SAndroid Build Coastguard Worker             return Some(region);
137*bb4ee6a4SAndroid Build Coastguard Worker         }
138*bb4ee6a4SAndroid Build Coastguard Worker 
139*bb4ee6a4SAndroid Build Coastguard Worker         None
140*bb4ee6a4SAndroid Build Coastguard Worker     }
141*bb4ee6a4SAndroid Build Coastguard Worker }
142*bb4ee6a4SAndroid Build Coastguard Worker 
143*bb4ee6a4SAndroid Build Coastguard Worker /// Trait for memory that can yield both iovecs in to the backing memory.
144*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
145*bb4ee6a4SAndroid Build Coastguard Worker /// Must be OK to modify the backing memory without owning a mut able reference. For example,
146*bb4ee6a4SAndroid Build Coastguard Worker /// this is safe for GuestMemory and VolatileSlices in crosvm as those types guarantee they are
147*bb4ee6a4SAndroid Build Coastguard Worker /// dealt with as volatile.
148*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe trait BackingMemory {
149*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns VolatileSlice pointing to the backing memory. This is most commonly unsafe.
150*bb4ee6a4SAndroid Build Coastguard Worker     /// To implement this safely the implementor must guarantee that the backing memory can be
151*bb4ee6a4SAndroid Build Coastguard Worker     /// modified out of band without affecting safety guarantees.
get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice>152*bb4ee6a4SAndroid Build Coastguard Worker     fn get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice>;
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper to be used for passing a Vec in as backing memory for asynchronous operations.  The
156*bb4ee6a4SAndroid Build Coastguard Worker /// wrapper owns a Vec according to the borrow checker. It is loaning this vec out to the kernel(or
157*bb4ee6a4SAndroid Build Coastguard Worker /// other modifiers) through the `BackingMemory` trait. This allows multiple modifiers of the array
158*bb4ee6a4SAndroid Build Coastguard Worker /// in the `Vec` while this struct is alive. The data in the Vec is loaned to the kernel not the
159*bb4ee6a4SAndroid Build Coastguard Worker /// data structure itself, the length, capacity, and pointer to memory cannot be modified.
160*bb4ee6a4SAndroid Build Coastguard Worker /// To ensure that those operations can be done safely, no access is allowed to the `Vec`'s memory
161*bb4ee6a4SAndroid Build Coastguard Worker /// starting at the time that `VecIoWrapper` is constructed until the time it is turned back in to a
162*bb4ee6a4SAndroid Build Coastguard Worker /// `Vec` using `to_inner`. The returned `Vec` is guaranteed to be valid as any combination of bits
163*bb4ee6a4SAndroid Build Coastguard Worker /// in a `Vec` of `u8` is valid.
164*bb4ee6a4SAndroid Build Coastguard Worker pub struct VecIoWrapper {
165*bb4ee6a4SAndroid Build Coastguard Worker     inner: Box<[u8]>,
166*bb4ee6a4SAndroid Build Coastguard Worker }
167*bb4ee6a4SAndroid Build Coastguard Worker 
168*bb4ee6a4SAndroid Build Coastguard Worker impl From<Vec<u8>> for VecIoWrapper {
from(vec: Vec<u8>) -> Self169*bb4ee6a4SAndroid Build Coastguard Worker     fn from(vec: Vec<u8>) -> Self {
170*bb4ee6a4SAndroid Build Coastguard Worker         VecIoWrapper { inner: vec.into() }
171*bb4ee6a4SAndroid Build Coastguard Worker     }
172*bb4ee6a4SAndroid Build Coastguard Worker }
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker impl From<VecIoWrapper> for Vec<u8> {
from(v: VecIoWrapper) -> Vec<u8>175*bb4ee6a4SAndroid Build Coastguard Worker     fn from(v: VecIoWrapper) -> Vec<u8> {
176*bb4ee6a4SAndroid Build Coastguard Worker         v.inner.into()
177*bb4ee6a4SAndroid Build Coastguard Worker     }
178*bb4ee6a4SAndroid Build Coastguard Worker }
179*bb4ee6a4SAndroid Build Coastguard Worker 
180*bb4ee6a4SAndroid Build Coastguard Worker impl VecIoWrapper {
181*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the length of the Vec that is wrapped.
182*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg_attr(windows, allow(dead_code))]
len(&self) -> usize183*bb4ee6a4SAndroid Build Coastguard Worker     pub fn len(&self) -> usize {
184*bb4ee6a4SAndroid Build Coastguard Worker         self.inner.len()
185*bb4ee6a4SAndroid Build Coastguard Worker     }
186*bb4ee6a4SAndroid Build Coastguard Worker 
is_empty(&self) -> bool187*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_empty(&self) -> bool {
188*bb4ee6a4SAndroid Build Coastguard Worker         self.len() == 0
189*bb4ee6a4SAndroid Build Coastguard Worker     }
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker     // Check that the offsets are all valid in the backing vec.
check_addrs(&self, mem_range: &MemRegion) -> Result<()>192*bb4ee6a4SAndroid Build Coastguard Worker     fn check_addrs(&self, mem_range: &MemRegion) -> Result<()> {
193*bb4ee6a4SAndroid Build Coastguard Worker         let end = mem_range
194*bb4ee6a4SAndroid Build Coastguard Worker             .offset
195*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(mem_range.len as u64)
196*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidOffset(mem_range.offset, mem_range.len))?;
197*bb4ee6a4SAndroid Build Coastguard Worker         if end > self.inner.len() as u64 {
198*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidOffset(mem_range.offset, mem_range.len));
199*bb4ee6a4SAndroid Build Coastguard Worker         }
200*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
201*bb4ee6a4SAndroid Build Coastguard Worker     }
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
205*bb4ee6a4SAndroid Build Coastguard Worker // Safe to implement BackingMemory as the vec is only accessible inside the wrapper and these iovecs
206*bb4ee6a4SAndroid Build Coastguard Worker // are the only thing allowed to modify it.  Nothing else can get a reference to the vec until all
207*bb4ee6a4SAndroid Build Coastguard Worker // iovecs are dropped because they borrow Self.  Nothing can borrow the owned inner vec until self
208*bb4ee6a4SAndroid Build Coastguard Worker // is consumed by `into`, which can't happen if there are outstanding mut borrows.
209*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl BackingMemory for VecIoWrapper {
get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice<'_>>210*bb4ee6a4SAndroid Build Coastguard Worker     fn get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice<'_>> {
211*bb4ee6a4SAndroid Build Coastguard Worker         self.check_addrs(&mem_range)?;
212*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
213*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the mem_range range is valid in the backing memory as checked above.
214*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
215*bb4ee6a4SAndroid Build Coastguard Worker             Ok(VolatileSlice::from_raw_parts(
216*bb4ee6a4SAndroid Build Coastguard Worker                 self.inner.as_ptr().add(mem_range.offset as usize) as *mut _,
217*bb4ee6a4SAndroid Build Coastguard Worker                 mem_range.len,
218*bb4ee6a4SAndroid Build Coastguard Worker             ))
219*bb4ee6a4SAndroid Build Coastguard Worker         }
220*bb4ee6a4SAndroid Build Coastguard Worker     }
221*bb4ee6a4SAndroid Build Coastguard Worker }
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
224*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
225*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
226*bb4ee6a4SAndroid Build Coastguard Worker 
227*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_empty()228*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_empty() {
229*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[]);
230*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
231*bb4ee6a4SAndroid Build Coastguard Worker     }
232*bb4ee6a4SAndroid Build Coastguard Worker 
233*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one()234*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one() {
235*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]);
236*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
237*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
238*bb4ee6a4SAndroid Build Coastguard Worker     }
239*bb4ee6a4SAndroid Build Coastguard Worker 
240*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_len_usize_max()241*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_len_usize_max() {
242*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion {
243*bb4ee6a4SAndroid Build Coastguard Worker             offset: 0,
244*bb4ee6a4SAndroid Build Coastguard Worker             len: usize::MAX,
245*bb4ee6a4SAndroid Build Coastguard Worker         }]);
246*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
247*bb4ee6a4SAndroid Build Coastguard Worker             iter.next(),
248*bb4ee6a4SAndroid Build Coastguard Worker             Some(MemRegion {
249*bb4ee6a4SAndroid Build Coastguard Worker                 offset: 0,
250*bb4ee6a4SAndroid Build Coastguard Worker                 len: usize::MAX
251*bb4ee6a4SAndroid Build Coastguard Worker             })
252*bb4ee6a4SAndroid Build Coastguard Worker         );
253*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
254*bb4ee6a4SAndroid Build Coastguard Worker     }
255*bb4ee6a4SAndroid Build Coastguard Worker 
256*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_len_zero()257*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_len_zero() {
258*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 0 }]);
259*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
260*bb4ee6a4SAndroid Build Coastguard Worker     }
261*bb4ee6a4SAndroid Build Coastguard Worker 
262*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_skip_partial()263*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_skip_partial() {
264*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(1);
265*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 3 }));
266*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
267*bb4ee6a4SAndroid Build Coastguard Worker     }
268*bb4ee6a4SAndroid Build Coastguard Worker 
269*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_skip_full()270*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_skip_full() {
271*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(4);
272*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
273*bb4ee6a4SAndroid Build Coastguard Worker     }
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_skip_excess()276*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_skip_excess() {
277*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(5);
278*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
279*bb4ee6a4SAndroid Build Coastguard Worker     }
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_take_zero()282*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_take_zero() {
283*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(0);
284*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
285*bb4ee6a4SAndroid Build Coastguard Worker     }
286*bb4ee6a4SAndroid Build Coastguard Worker 
287*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_take_partial()288*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_take_partial() {
289*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(1);
290*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 1 }));
291*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
292*bb4ee6a4SAndroid Build Coastguard Worker     }
293*bb4ee6a4SAndroid Build Coastguard Worker 
294*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_take_full()295*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_take_full() {
296*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(4);
297*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
298*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
299*bb4ee6a4SAndroid Build Coastguard Worker     }
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_take_excess()302*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_take_excess() {
303*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(5);
304*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
305*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
306*bb4ee6a4SAndroid Build Coastguard Worker     }
307*bb4ee6a4SAndroid Build Coastguard Worker 
308*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_take_skip()309*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_take_skip() {
310*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }])
311*bb4ee6a4SAndroid Build Coastguard Worker             .take_bytes(2)
312*bb4ee6a4SAndroid Build Coastguard Worker             .skip_bytes(1);
313*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 1 }));
314*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
315*bb4ee6a4SAndroid Build Coastguard Worker     }
316*bb4ee6a4SAndroid Build Coastguard Worker 
317*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_one_skip_take()318*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_one_skip_take() {
319*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }])
320*bb4ee6a4SAndroid Build Coastguard Worker             .skip_bytes(1)
321*bb4ee6a4SAndroid Build Coastguard Worker             .take_bytes(2);
322*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 2 }));
323*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
324*bb4ee6a4SAndroid Build Coastguard Worker     }
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two()327*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two() {
328*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
329*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
330*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
331*bb4ee6a4SAndroid Build Coastguard Worker         ]);
332*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
333*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
334*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
335*bb4ee6a4SAndroid Build Coastguard Worker     }
336*bb4ee6a4SAndroid Build Coastguard Worker 
337*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_skip_partial()338*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_skip_partial() {
339*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
340*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
341*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
342*bb4ee6a4SAndroid Build Coastguard Worker         ])
343*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(1);
344*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 3 }));
345*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
346*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
347*bb4ee6a4SAndroid Build Coastguard Worker     }
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_skip_full()350*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_skip_full() {
351*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
352*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
353*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
354*bb4ee6a4SAndroid Build Coastguard Worker         ])
355*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(4);
356*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
357*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
358*bb4ee6a4SAndroid Build Coastguard Worker     }
359*bb4ee6a4SAndroid Build Coastguard Worker 
360*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_skip_excess()361*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_skip_excess() {
362*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
363*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
364*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
365*bb4ee6a4SAndroid Build Coastguard Worker         ])
366*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(5);
367*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 9, len: 1 }));
368*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
369*bb4ee6a4SAndroid Build Coastguard Worker     }
370*bb4ee6a4SAndroid Build Coastguard Worker 
371*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_skip_multi()372*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_skip_multi() {
373*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
374*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
375*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
376*bb4ee6a4SAndroid Build Coastguard Worker         ])
377*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(6);
378*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
379*bb4ee6a4SAndroid Build Coastguard Worker     }
380*bb4ee6a4SAndroid Build Coastguard Worker 
381*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_take_partial()382*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_take_partial() {
383*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
384*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
385*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
386*bb4ee6a4SAndroid Build Coastguard Worker         ])
387*bb4ee6a4SAndroid Build Coastguard Worker         .take_bytes(1);
388*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 1 }));
389*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
390*bb4ee6a4SAndroid Build Coastguard Worker     }
391*bb4ee6a4SAndroid Build Coastguard Worker 
392*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_take_partial2()393*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_take_partial2() {
394*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
395*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
396*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
397*bb4ee6a4SAndroid Build Coastguard Worker         ])
398*bb4ee6a4SAndroid Build Coastguard Worker         .take_bytes(5);
399*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
400*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 1 }));
401*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
402*bb4ee6a4SAndroid Build Coastguard Worker     }
403*bb4ee6a4SAndroid Build Coastguard Worker 
404*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_take_full()405*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_take_full() {
406*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
407*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
408*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
409*bb4ee6a4SAndroid Build Coastguard Worker         ])
410*bb4ee6a4SAndroid Build Coastguard Worker         .take_bytes(6);
411*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
412*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
413*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
414*bb4ee6a4SAndroid Build Coastguard Worker     }
415*bb4ee6a4SAndroid Build Coastguard Worker 
416*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_two_take_excess()417*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_two_take_excess() {
418*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
419*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
420*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
421*bb4ee6a4SAndroid Build Coastguard Worker         ])
422*bb4ee6a4SAndroid Build Coastguard Worker         .take_bytes(7);
423*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 }));
424*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
425*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
426*bb4ee6a4SAndroid Build Coastguard Worker     }
427*bb4ee6a4SAndroid Build Coastguard Worker 
428*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_embedded_zero_len()429*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_embedded_zero_len() {
430*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
431*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
432*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
433*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 9, len: 0 },
434*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 16, len: 5 },
435*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 6, len: 0 },
436*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 24, len: 9 },
437*bb4ee6a4SAndroid Build Coastguard Worker         ])
438*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(2)
439*bb4ee6a4SAndroid Build Coastguard Worker         .take_bytes(12);
440*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 2, len: 2 }));
441*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 }));
442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 16, len: 5 }));
443*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 24, len: 3 }));
444*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
445*bb4ee6a4SAndroid Build Coastguard Worker     }
446*bb4ee6a4SAndroid Build Coastguard Worker 
447*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
mem_region_iter_skip_multi()448*bb4ee6a4SAndroid Build Coastguard Worker     fn mem_region_iter_skip_multi() {
449*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = MemRegionIter::new(&[
450*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 0, len: 4 },
451*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 8, len: 2 },
452*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 16, len: 5 },
453*bb4ee6a4SAndroid Build Coastguard Worker             MemRegion { offset: 24, len: 9 },
454*bb4ee6a4SAndroid Build Coastguard Worker         ])
455*bb4ee6a4SAndroid Build Coastguard Worker         .skip_bytes(7);
456*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 17, len: 4 }));
457*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(MemRegion { offset: 24, len: 9 }));
458*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), None);
459*bb4ee6a4SAndroid Build Coastguard Worker     }
460*bb4ee6a4SAndroid Build Coastguard Worker }
461