xref: /aosp_15_r20/external/crosvm/cros_async/src/io_source.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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