1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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 std::sync::Arc; 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 8*bb4ee6a4SAndroid Build Coastguard Worker 9*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 10*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::linux::PollSource; 11*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 12*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::linux::UringSource; 13*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "tokio")] 14*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::platform::tokio_source::TokioSource; 15*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 16*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::HandleSource; 17*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 18*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::OverlappedSource; 19*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsyncResult; 20*bb4ee6a4SAndroid Build Coastguard Worker use crate::BackingMemory; 21*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemRegion; 22*bb4ee6a4SAndroid Build Coastguard Worker 23*bb4ee6a4SAndroid Build Coastguard Worker /// Associates an IO object `F` with cros_async's runtime and exposes an API to perform async IO on 24*bb4ee6a4SAndroid Build Coastguard Worker /// that object's descriptor. 25*bb4ee6a4SAndroid Build Coastguard Worker pub enum IoSource<F: base::AsRawDescriptor> { 26*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 27*bb4ee6a4SAndroid Build Coastguard Worker Uring(UringSource<F>), 28*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 29*bb4ee6a4SAndroid Build Coastguard Worker Epoll(PollSource<F>), 30*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 31*bb4ee6a4SAndroid Build Coastguard Worker Handle(HandleSource<F>), 32*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 33*bb4ee6a4SAndroid Build Coastguard Worker Overlapped(OverlappedSource<F>), 34*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "tokio")] 35*bb4ee6a4SAndroid Build Coastguard Worker Tokio(TokioSource<F>), 36*bb4ee6a4SAndroid Build Coastguard Worker } 37*bb4ee6a4SAndroid Build Coastguard Worker 38*bb4ee6a4SAndroid Build Coastguard Worker static_assertions::assert_impl_all!(IoSource<std::fs::File>: Send, Sync); 39*bb4ee6a4SAndroid Build Coastguard Worker 40*bb4ee6a4SAndroid Build Coastguard Worker /// Invoke a method on the underlying source type and await the result. 41*bb4ee6a4SAndroid Build Coastguard Worker /// 42*bb4ee6a4SAndroid Build Coastguard Worker /// `await_on_inner(io_source, method, ...)` => `inner_source.method(...).await` 43*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! await_on_inner { 44*bb4ee6a4SAndroid Build Coastguard Worker ($x:ident, $method:ident $(, $args:expr)*) => { 45*bb4ee6a4SAndroid Build Coastguard Worker match $x { 46*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 47*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Uring(x) => UringSource::$method(x, $($args),*).await, 48*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 49*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Epoll(x) => PollSource::$method(x, $($args),*).await, 50*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 51*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Handle(x) => HandleSource::$method(x, $($args),*).await, 52*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 53*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Overlapped(x) => OverlappedSource::$method(x, $($args),*).await, 54*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "tokio")] 55*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Tokio(x) => TokioSource::$method(x, $($args),*).await, 56*bb4ee6a4SAndroid Build Coastguard Worker } 57*bb4ee6a4SAndroid Build Coastguard Worker }; 58*bb4ee6a4SAndroid Build Coastguard Worker } 59*bb4ee6a4SAndroid Build Coastguard Worker 60*bb4ee6a4SAndroid Build Coastguard Worker /// Invoke a method on the underlying source type. 61*bb4ee6a4SAndroid Build Coastguard Worker /// 62*bb4ee6a4SAndroid Build Coastguard Worker /// `on_inner(io_source, method, ...)` => `inner_source.method(...)` 63*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! on_inner { 64*bb4ee6a4SAndroid Build Coastguard Worker ($x:ident, $method:ident $(, $args:expr)*) => { 65*bb4ee6a4SAndroid Build Coastguard Worker match $x { 66*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 67*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Uring(x) => UringSource::$method(x, $($args),*), 68*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 69*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Epoll(x) => PollSource::$method(x, $($args),*), 70*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 71*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Handle(x) => HandleSource::$method(x, $($args),*), 72*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 73*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Overlapped(x) => OverlappedSource::$method(x, $($args),*), 74*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "tokio")] 75*bb4ee6a4SAndroid Build Coastguard Worker IoSource::Tokio(x) => TokioSource::$method(x, $($args),*), 76*bb4ee6a4SAndroid Build Coastguard Worker } 77*bb4ee6a4SAndroid Build Coastguard Worker }; 78*bb4ee6a4SAndroid Build Coastguard Worker } 79*bb4ee6a4SAndroid Build Coastguard Worker 80*bb4ee6a4SAndroid Build Coastguard Worker impl<F: AsRawDescriptor> IoSource<F> { 81*bb4ee6a4SAndroid Build Coastguard Worker /// Reads at `file_offset` and fills the given `vec`. read_to_vec( &self, file_offset: Option<u64>, vec: Vec<u8>, ) -> AsyncResult<(usize, Vec<u8>)>82*bb4ee6a4SAndroid Build Coastguard Worker pub async fn read_to_vec( 83*bb4ee6a4SAndroid Build Coastguard Worker &self, 84*bb4ee6a4SAndroid Build Coastguard Worker file_offset: Option<u64>, 85*bb4ee6a4SAndroid Build Coastguard Worker vec: Vec<u8>, 86*bb4ee6a4SAndroid Build Coastguard Worker ) -> AsyncResult<(usize, Vec<u8>)> { 87*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, read_to_vec, file_offset, vec) 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker 90*bb4ee6a4SAndroid Build Coastguard Worker /// Reads to the given `mem` at the given offsets from the file starting at `file_offset`. read_to_mem( &self, file_offset: Option<u64>, mem: Arc<dyn BackingMemory + Send + Sync>, mem_offsets: impl IntoIterator<Item = MemRegion>, ) -> AsyncResult<usize>91*bb4ee6a4SAndroid Build Coastguard Worker pub async fn read_to_mem( 92*bb4ee6a4SAndroid Build Coastguard Worker &self, 93*bb4ee6a4SAndroid Build Coastguard Worker file_offset: Option<u64>, 94*bb4ee6a4SAndroid Build Coastguard Worker mem: Arc<dyn BackingMemory + Send + Sync>, 95*bb4ee6a4SAndroid Build Coastguard Worker mem_offsets: impl IntoIterator<Item = MemRegion>, 96*bb4ee6a4SAndroid Build Coastguard Worker ) -> AsyncResult<usize> { 97*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, read_to_mem, file_offset, mem, mem_offsets) 98*bb4ee6a4SAndroid Build Coastguard Worker } 99*bb4ee6a4SAndroid Build Coastguard Worker 100*bb4ee6a4SAndroid Build Coastguard Worker /// Waits for the object to be readable. wait_readable(&self) -> AsyncResult<()>101*bb4ee6a4SAndroid Build Coastguard Worker pub async fn wait_readable(&self) -> AsyncResult<()> { 102*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, wait_readable) 103*bb4ee6a4SAndroid Build Coastguard Worker } 104*bb4ee6a4SAndroid Build Coastguard Worker 105*bb4ee6a4SAndroid Build Coastguard Worker /// Writes from the given `vec` to the file starting at `file_offset`. write_from_vec( &self, file_offset: Option<u64>, vec: Vec<u8>, ) -> AsyncResult<(usize, Vec<u8>)>106*bb4ee6a4SAndroid Build Coastguard Worker pub async fn write_from_vec( 107*bb4ee6a4SAndroid Build Coastguard Worker &self, 108*bb4ee6a4SAndroid Build Coastguard Worker file_offset: Option<u64>, 109*bb4ee6a4SAndroid Build Coastguard Worker vec: Vec<u8>, 110*bb4ee6a4SAndroid Build Coastguard Worker ) -> AsyncResult<(usize, Vec<u8>)> { 111*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, write_from_vec, file_offset, vec) 112*bb4ee6a4SAndroid Build Coastguard Worker } 113*bb4ee6a4SAndroid Build Coastguard Worker 114*bb4ee6a4SAndroid Build Coastguard Worker /// Writes from the given `mem` at the given offsets to the file starting at `file_offset`. write_from_mem( &self, file_offset: Option<u64>, mem: Arc<dyn BackingMemory + Send + Sync>, mem_offsets: impl IntoIterator<Item = MemRegion>, ) -> AsyncResult<usize>115*bb4ee6a4SAndroid Build Coastguard Worker pub async fn write_from_mem( 116*bb4ee6a4SAndroid Build Coastguard Worker &self, 117*bb4ee6a4SAndroid Build Coastguard Worker file_offset: Option<u64>, 118*bb4ee6a4SAndroid Build Coastguard Worker mem: Arc<dyn BackingMemory + Send + Sync>, 119*bb4ee6a4SAndroid Build Coastguard Worker mem_offsets: impl IntoIterator<Item = MemRegion>, 120*bb4ee6a4SAndroid Build Coastguard Worker ) -> AsyncResult<usize> { 121*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, write_from_mem, file_offset, mem, mem_offsets) 122*bb4ee6a4SAndroid Build Coastguard Worker } 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker /// Deallocates the given range of a file. punch_hole(&self, file_offset: u64, len: u64) -> AsyncResult<()>125*bb4ee6a4SAndroid Build Coastguard Worker pub async fn punch_hole(&self, file_offset: u64, len: u64) -> AsyncResult<()> { 126*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, punch_hole, file_offset, len) 127*bb4ee6a4SAndroid Build Coastguard Worker } 128*bb4ee6a4SAndroid Build Coastguard Worker 129*bb4ee6a4SAndroid Build Coastguard Worker /// Fills the given range with zeroes. write_zeroes_at(&self, file_offset: u64, len: u64) -> AsyncResult<()>130*bb4ee6a4SAndroid Build Coastguard Worker pub async fn write_zeroes_at(&self, file_offset: u64, len: u64) -> AsyncResult<()> { 131*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, write_zeroes_at, file_offset, len) 132*bb4ee6a4SAndroid Build Coastguard Worker } 133*bb4ee6a4SAndroid Build Coastguard Worker 134*bb4ee6a4SAndroid Build Coastguard Worker /// Sync all completed write operations to the backing storage. fsync(&self) -> AsyncResult<()>135*bb4ee6a4SAndroid Build Coastguard Worker pub async fn fsync(&self) -> AsyncResult<()> { 136*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, fsync) 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker 139*bb4ee6a4SAndroid Build Coastguard Worker /// Sync all data of completed write operations to the backing storage, avoiding updating extra 140*bb4ee6a4SAndroid Build Coastguard Worker /// metadata. Note that an implementation may simply implement fsync for fdatasync. fdatasync(&self) -> AsyncResult<()>141*bb4ee6a4SAndroid Build Coastguard Worker pub async fn fdatasync(&self) -> AsyncResult<()> { 142*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, fdatasync) 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker 145*bb4ee6a4SAndroid Build Coastguard Worker /// Yields the underlying IO source. into_source(self) -> F146*bb4ee6a4SAndroid Build Coastguard Worker pub fn into_source(self) -> F { 147*bb4ee6a4SAndroid Build Coastguard Worker on_inner!(self, into_source) 148*bb4ee6a4SAndroid Build Coastguard Worker } 149*bb4ee6a4SAndroid Build Coastguard Worker 150*bb4ee6a4SAndroid Build Coastguard Worker /// Provides a ref to the underlying IO source. as_source(&self) -> &F151*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_source(&self) -> &F { 152*bb4ee6a4SAndroid Build Coastguard Worker on_inner!(self, as_source) 153*bb4ee6a4SAndroid Build Coastguard Worker } 154*bb4ee6a4SAndroid Build Coastguard Worker 155*bb4ee6a4SAndroid Build Coastguard Worker /// Provides a mutable ref to the underlying IO source. as_source_mut(&mut self) -> &mut F156*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_source_mut(&mut self) -> &mut F { 157*bb4ee6a4SAndroid Build Coastguard Worker on_inner!(self, as_source_mut) 158*bb4ee6a4SAndroid Build Coastguard Worker } 159*bb4ee6a4SAndroid Build Coastguard Worker 160*bb4ee6a4SAndroid Build Coastguard Worker /// Waits on a waitable handle. 161*bb4ee6a4SAndroid Build Coastguard Worker /// 162*bb4ee6a4SAndroid Build Coastguard Worker /// Needed for Windows currently, and subject to a potential future upstream. 163*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] wait_for_handle(&self) -> AsyncResult<()>164*bb4ee6a4SAndroid Build Coastguard Worker pub async fn wait_for_handle(&self) -> AsyncResult<()> { 165*bb4ee6a4SAndroid Build Coastguard Worker await_on_inner!(self, wait_for_handle) 166*bb4ee6a4SAndroid Build Coastguard Worker } 167*bb4ee6a4SAndroid Build Coastguard Worker } 168*bb4ee6a4SAndroid Build Coastguard Worker 169*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 170*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 171*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File; 172*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read; 173*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek; 174*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom; 175*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 176*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 177*bb4ee6a4SAndroid Build Coastguard Worker 178*bb4ee6a4SAndroid Build Coastguard Worker use tempfile::tempfile; 179*bb4ee6a4SAndroid Build Coastguard Worker 180*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 181*bb4ee6a4SAndroid Build Coastguard Worker use crate::mem::VecIoWrapper; 182*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] 183*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::linux::uring_executor::is_uring_stable; 184*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::ExecutorKindSys; 185*bb4ee6a4SAndroid Build Coastguard Worker use crate::Executor; 186*bb4ee6a4SAndroid Build Coastguard Worker use crate::ExecutorKind; 187*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemRegion; 188*bb4ee6a4SAndroid Build Coastguard Worker 189*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] all_kinds() -> Vec<ExecutorKind>190*bb4ee6a4SAndroid Build Coastguard Worker fn all_kinds() -> Vec<ExecutorKind> { 191*bb4ee6a4SAndroid Build Coastguard Worker let mut kinds = vec![ExecutorKindSys::Fd.into()]; 192*bb4ee6a4SAndroid Build Coastguard Worker if is_uring_stable() { 193*bb4ee6a4SAndroid Build Coastguard Worker kinds.push(ExecutorKindSys::Uring.into()); 194*bb4ee6a4SAndroid Build Coastguard Worker } 195*bb4ee6a4SAndroid Build Coastguard Worker kinds 196*bb4ee6a4SAndroid Build Coastguard Worker } 197*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] all_kinds() -> Vec<ExecutorKind>198*bb4ee6a4SAndroid Build Coastguard Worker fn all_kinds() -> Vec<ExecutorKind> { 199*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Test OverlappedSource. It requires files to be opened specially, so this test 200*bb4ee6a4SAndroid Build Coastguard Worker // fixture needs to be refactored first. 201*bb4ee6a4SAndroid Build Coastguard Worker vec![ExecutorKindSys::Handle.into()] 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker tmpfile_with_contents(bytes: &[u8]) -> File204*bb4ee6a4SAndroid Build Coastguard Worker fn tmpfile_with_contents(bytes: &[u8]) -> File { 205*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tempfile().unwrap(); 206*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(bytes).unwrap(); 207*bb4ee6a4SAndroid Build Coastguard Worker f.flush().unwrap(); 208*bb4ee6a4SAndroid Build Coastguard Worker f.seek(SeekFrom::Start(0)).unwrap(); 209*bb4ee6a4SAndroid Build Coastguard Worker f 210*bb4ee6a4SAndroid Build Coastguard Worker } 211*bb4ee6a4SAndroid Build Coastguard Worker 212*bb4ee6a4SAndroid Build Coastguard Worker #[test] readvec()213*bb4ee6a4SAndroid Build Coastguard Worker fn readvec() { 214*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 215*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(async_source: IoSource<F>) { 216*bb4ee6a4SAndroid Build Coastguard Worker let v = vec![0x55u8; 32]; 217*bb4ee6a4SAndroid Build Coastguard Worker let v_ptr = v.as_ptr(); 218*bb4ee6a4SAndroid Build Coastguard Worker let (n, v) = async_source.read_to_vec(None, v).await.unwrap(); 219*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(v_ptr, v.as_ptr()); 220*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(n, 4); 221*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(&v[..4], "data".as_bytes()); 222*bb4ee6a4SAndroid Build Coastguard Worker } 223*bb4ee6a4SAndroid Build Coastguard Worker 224*bb4ee6a4SAndroid Build Coastguard Worker let f = tmpfile_with_contents("data".as_bytes()); 225*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 226*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 227*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 228*bb4ee6a4SAndroid Build Coastguard Worker } 229*bb4ee6a4SAndroid Build Coastguard Worker } 230*bb4ee6a4SAndroid Build Coastguard Worker 231*bb4ee6a4SAndroid Build Coastguard Worker #[test] writevec()232*bb4ee6a4SAndroid Build Coastguard Worker fn writevec() { 233*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 234*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(async_source: IoSource<F>) { 235*bb4ee6a4SAndroid Build Coastguard Worker let v = "data".as_bytes().to_vec(); 236*bb4ee6a4SAndroid Build Coastguard Worker let v_ptr = v.as_ptr(); 237*bb4ee6a4SAndroid Build Coastguard Worker let (n, v) = async_source.write_from_vec(None, v).await.unwrap(); 238*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(n, 4); 239*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(v_ptr, v.as_ptr()); 240*bb4ee6a4SAndroid Build Coastguard Worker } 241*bb4ee6a4SAndroid Build Coastguard Worker 242*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tmpfile_with_contents(&[]); 243*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 244*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f.try_clone().unwrap()).unwrap(); 245*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 246*bb4ee6a4SAndroid Build Coastguard Worker 247*bb4ee6a4SAndroid Build Coastguard Worker f.rewind().unwrap(); 248*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(std::io::read_to_string(f).unwrap(), "data"); 249*bb4ee6a4SAndroid Build Coastguard Worker } 250*bb4ee6a4SAndroid Build Coastguard Worker } 251*bb4ee6a4SAndroid Build Coastguard Worker 252*bb4ee6a4SAndroid Build Coastguard Worker #[test] readmem()253*bb4ee6a4SAndroid Build Coastguard Worker fn readmem() { 254*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 255*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(async_source: IoSource<F>) { 256*bb4ee6a4SAndroid Build Coastguard Worker let mem = Arc::new(VecIoWrapper::from(vec![b' '; 10])); 257*bb4ee6a4SAndroid Build Coastguard Worker let n = async_source 258*bb4ee6a4SAndroid Build Coastguard Worker .read_to_mem( 259*bb4ee6a4SAndroid Build Coastguard Worker None, 260*bb4ee6a4SAndroid Build Coastguard Worker Arc::<VecIoWrapper>::clone(&mem), 261*bb4ee6a4SAndroid Build Coastguard Worker [ 262*bb4ee6a4SAndroid Build Coastguard Worker MemRegion { offset: 0, len: 2 }, 263*bb4ee6a4SAndroid Build Coastguard Worker MemRegion { offset: 4, len: 1 }, 264*bb4ee6a4SAndroid Build Coastguard Worker ], 265*bb4ee6a4SAndroid Build Coastguard Worker ) 266*bb4ee6a4SAndroid Build Coastguard Worker .await 267*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 268*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(n, 3); 269*bb4ee6a4SAndroid Build Coastguard Worker let vec: Vec<u8> = match Arc::try_unwrap(mem) { 270*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v.into(), 271*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("Too many vec refs"), 272*bb4ee6a4SAndroid Build Coastguard Worker }; 273*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(std::str::from_utf8(&vec).unwrap(), "da t "); 274*bb4ee6a4SAndroid Build Coastguard Worker } 275*bb4ee6a4SAndroid Build Coastguard Worker 276*bb4ee6a4SAndroid Build Coastguard Worker let f = tmpfile_with_contents("data".as_bytes()); 277*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 278*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 279*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 280*bb4ee6a4SAndroid Build Coastguard Worker } 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker 283*bb4ee6a4SAndroid Build Coastguard Worker #[test] writemem()284*bb4ee6a4SAndroid Build Coastguard Worker fn writemem() { 285*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 286*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(async_source: IoSource<F>) { 287*bb4ee6a4SAndroid Build Coastguard Worker let mem = Arc::new(VecIoWrapper::from("data".as_bytes().to_vec())); 288*bb4ee6a4SAndroid Build Coastguard Worker let ret = async_source 289*bb4ee6a4SAndroid Build Coastguard Worker .write_from_mem( 290*bb4ee6a4SAndroid Build Coastguard Worker None, 291*bb4ee6a4SAndroid Build Coastguard Worker Arc::<VecIoWrapper>::clone(&mem), 292*bb4ee6a4SAndroid Build Coastguard Worker [ 293*bb4ee6a4SAndroid Build Coastguard Worker MemRegion { offset: 0, len: 1 }, 294*bb4ee6a4SAndroid Build Coastguard Worker MemRegion { offset: 2, len: 2 }, 295*bb4ee6a4SAndroid Build Coastguard Worker ], 296*bb4ee6a4SAndroid Build Coastguard Worker ) 297*bb4ee6a4SAndroid Build Coastguard Worker .await 298*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 299*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(ret, 3); 300*bb4ee6a4SAndroid Build Coastguard Worker } 301*bb4ee6a4SAndroid Build Coastguard Worker 302*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tmpfile_with_contents(&[]); 303*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 304*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f.try_clone().unwrap()).unwrap(); 305*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 306*bb4ee6a4SAndroid Build Coastguard Worker 307*bb4ee6a4SAndroid Build Coastguard Worker f.rewind().unwrap(); 308*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(std::io::read_to_string(f).unwrap(), "dta"); 309*bb4ee6a4SAndroid Build Coastguard Worker } 310*bb4ee6a4SAndroid Build Coastguard Worker } 311*bb4ee6a4SAndroid Build Coastguard Worker 312*bb4ee6a4SAndroid Build Coastguard Worker #[test] fsync()313*bb4ee6a4SAndroid Build Coastguard Worker fn fsync() { 314*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 315*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(source: IoSource<F>) { 316*bb4ee6a4SAndroid Build Coastguard Worker let v = vec![0x55u8; 32]; 317*bb4ee6a4SAndroid Build Coastguard Worker let v_ptr = v.as_ptr(); 318*bb4ee6a4SAndroid Build Coastguard Worker let ret = source.write_from_vec(None, v).await.unwrap(); 319*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(ret.0, 32); 320*bb4ee6a4SAndroid Build Coastguard Worker let ret_v = ret.1; 321*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(v_ptr, ret_v.as_ptr()); 322*bb4ee6a4SAndroid Build Coastguard Worker source.fsync().await.unwrap(); 323*bb4ee6a4SAndroid Build Coastguard Worker } 324*bb4ee6a4SAndroid Build Coastguard Worker 325*bb4ee6a4SAndroid Build Coastguard Worker let f = tempfile::tempfile().unwrap(); 326*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 327*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 328*bb4ee6a4SAndroid Build Coastguard Worker 329*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 330*bb4ee6a4SAndroid Build Coastguard Worker } 331*bb4ee6a4SAndroid Build Coastguard Worker } 332*bb4ee6a4SAndroid Build Coastguard Worker 333*bb4ee6a4SAndroid Build Coastguard Worker #[test] readmulti()334*bb4ee6a4SAndroid Build Coastguard Worker fn readmulti() { 335*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 336*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(source: IoSource<F>) { 337*bb4ee6a4SAndroid Build Coastguard Worker let v = vec![0x55u8; 32]; 338*bb4ee6a4SAndroid Build Coastguard Worker let v2 = vec![0x55u8; 32]; 339*bb4ee6a4SAndroid Build Coastguard Worker let (ret, ret2) = futures::future::join( 340*bb4ee6a4SAndroid Build Coastguard Worker source.read_to_vec(None, v), 341*bb4ee6a4SAndroid Build Coastguard Worker source.read_to_vec(Some(32), v2), 342*bb4ee6a4SAndroid Build Coastguard Worker ) 343*bb4ee6a4SAndroid Build Coastguard Worker .await; 344*bb4ee6a4SAndroid Build Coastguard Worker 345*bb4ee6a4SAndroid Build Coastguard Worker let (count, v) = ret.unwrap(); 346*bb4ee6a4SAndroid Build Coastguard Worker let (count2, v2) = ret2.unwrap(); 347*bb4ee6a4SAndroid Build Coastguard Worker 348*bb4ee6a4SAndroid Build Coastguard Worker assert!(v.iter().take(count).all(|&b| b == 0xAA)); 349*bb4ee6a4SAndroid Build Coastguard Worker assert!(v2.iter().take(count2).all(|&b| b == 0xBB)); 350*bb4ee6a4SAndroid Build Coastguard Worker } 351*bb4ee6a4SAndroid Build Coastguard Worker 352*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tempfile::tempfile().unwrap(); 353*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(&[0xAA; 32]).unwrap(); 354*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(&[0xBB; 32]).unwrap(); 355*bb4ee6a4SAndroid Build Coastguard Worker f.rewind().unwrap(); 356*bb4ee6a4SAndroid Build Coastguard Worker 357*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 358*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 359*bb4ee6a4SAndroid Build Coastguard Worker 360*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 361*bb4ee6a4SAndroid Build Coastguard Worker } 362*bb4ee6a4SAndroid Build Coastguard Worker } 363*bb4ee6a4SAndroid Build Coastguard Worker 364*bb4ee6a4SAndroid Build Coastguard Worker #[test] writemulti()365*bb4ee6a4SAndroid Build Coastguard Worker fn writemulti() { 366*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 367*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(source: IoSource<F>) { 368*bb4ee6a4SAndroid Build Coastguard Worker let v = vec![0x55u8; 32]; 369*bb4ee6a4SAndroid Build Coastguard Worker let v2 = vec![0x55u8; 32]; 370*bb4ee6a4SAndroid Build Coastguard Worker let (r, r2) = futures::future::join( 371*bb4ee6a4SAndroid Build Coastguard Worker source.write_from_vec(None, v), 372*bb4ee6a4SAndroid Build Coastguard Worker source.write_from_vec(Some(32), v2), 373*bb4ee6a4SAndroid Build Coastguard Worker ) 374*bb4ee6a4SAndroid Build Coastguard Worker .await; 375*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(32, r.unwrap().0); 376*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(32, r2.unwrap().0); 377*bb4ee6a4SAndroid Build Coastguard Worker } 378*bb4ee6a4SAndroid Build Coastguard Worker 379*bb4ee6a4SAndroid Build Coastguard Worker let f = tempfile::tempfile().unwrap(); 380*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 381*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 382*bb4ee6a4SAndroid Build Coastguard Worker 383*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 384*bb4ee6a4SAndroid Build Coastguard Worker } 385*bb4ee6a4SAndroid Build Coastguard Worker } 386*bb4ee6a4SAndroid Build Coastguard Worker 387*bb4ee6a4SAndroid Build Coastguard Worker #[test] read_current_file_position()388*bb4ee6a4SAndroid Build Coastguard Worker fn read_current_file_position() { 389*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 390*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(source: IoSource<F>) { 391*bb4ee6a4SAndroid Build Coastguard Worker let (count1, verify1) = source.read_to_vec(None, vec![0u8; 32]).await.unwrap(); 392*bb4ee6a4SAndroid Build Coastguard Worker let (count2, verify2) = source.read_to_vec(None, vec![0u8; 32]).await.unwrap(); 393*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(count1, 32); 394*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(count2, 32); 395*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(verify1, [0x55u8; 32]); 396*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(verify2, [0xffu8; 32]); 397*bb4ee6a4SAndroid Build Coastguard Worker } 398*bb4ee6a4SAndroid Build Coastguard Worker 399*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tempfile::tempfile().unwrap(); 400*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(&[0x55u8; 32]).unwrap(); 401*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(&[0xffu8; 32]).unwrap(); 402*bb4ee6a4SAndroid Build Coastguard Worker f.rewind().unwrap(); 403*bb4ee6a4SAndroid Build Coastguard Worker 404*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 405*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f).unwrap(); 406*bb4ee6a4SAndroid Build Coastguard Worker 407*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 408*bb4ee6a4SAndroid Build Coastguard Worker } 409*bb4ee6a4SAndroid Build Coastguard Worker } 410*bb4ee6a4SAndroid Build Coastguard Worker 411*bb4ee6a4SAndroid Build Coastguard Worker #[test] write_current_file_position()412*bb4ee6a4SAndroid Build Coastguard Worker fn write_current_file_position() { 413*bb4ee6a4SAndroid Build Coastguard Worker for kind in all_kinds() { 414*bb4ee6a4SAndroid Build Coastguard Worker async fn go<F: AsRawDescriptor>(source: IoSource<F>) { 415*bb4ee6a4SAndroid Build Coastguard Worker let count1 = source 416*bb4ee6a4SAndroid Build Coastguard Worker .write_from_vec(None, vec![0x55u8; 32]) 417*bb4ee6a4SAndroid Build Coastguard Worker .await 418*bb4ee6a4SAndroid Build Coastguard Worker .unwrap() 419*bb4ee6a4SAndroid Build Coastguard Worker .0; 420*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(count1, 32); 421*bb4ee6a4SAndroid Build Coastguard Worker let count2 = source 422*bb4ee6a4SAndroid Build Coastguard Worker .write_from_vec(None, vec![0xffu8; 32]) 423*bb4ee6a4SAndroid Build Coastguard Worker .await 424*bb4ee6a4SAndroid Build Coastguard Worker .unwrap() 425*bb4ee6a4SAndroid Build Coastguard Worker .0; 426*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(count2, 32); 427*bb4ee6a4SAndroid Build Coastguard Worker } 428*bb4ee6a4SAndroid Build Coastguard Worker 429*bb4ee6a4SAndroid Build Coastguard Worker let mut f = tempfile::tempfile().unwrap(); 430*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::with_executor_kind(kind).unwrap(); 431*bb4ee6a4SAndroid Build Coastguard Worker let source = ex.async_from(f.try_clone().unwrap()).unwrap(); 432*bb4ee6a4SAndroid Build Coastguard Worker 433*bb4ee6a4SAndroid Build Coastguard Worker ex.run_until(go(source)).unwrap(); 434*bb4ee6a4SAndroid Build Coastguard Worker 435*bb4ee6a4SAndroid Build Coastguard Worker f.rewind().unwrap(); 436*bb4ee6a4SAndroid Build Coastguard Worker let mut verify1 = [0u8; 32]; 437*bb4ee6a4SAndroid Build Coastguard Worker let mut verify2 = [0u8; 32]; 438*bb4ee6a4SAndroid Build Coastguard Worker f.read_exact(&mut verify1).unwrap(); 439*bb4ee6a4SAndroid Build Coastguard Worker f.read_exact(&mut verify2).unwrap(); 440*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(verify1, [0x55u8; 32]); 441*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(verify2, [0xffu8; 32]); 442*bb4ee6a4SAndroid Build Coastguard Worker } 443*bb4ee6a4SAndroid Build Coastguard Worker } 444*bb4ee6a4SAndroid Build Coastguard Worker } 445