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