impl tokio's AsyncRead/Write/Seek for AFC FileDescriptor (#33)

* AsyncWrite/Read/Seek

* clean up

* use only one field to store the future

This struct should not be shared across threads because simultaneous
operations
like reading, writing, or seeking could lead to data races or
inconsistent state, because the cursor moves.

Only one operation will ever run at a time, which allows us to safely
store
different types of pending operations (read, write, or seek) in the same
field.

* consume self without mut when closing

* clippy

* Add inner_file safety tests

* more tests

---------

Co-authored-by: Jackson Coxson <jkcoxson@gmail.com>
This commit is contained in:
Abdullah Al-Banna
2025-10-28 16:57:35 +03:00
committed by GitHub
parent 105a9b2837
commit b26dd17b13
7 changed files with 827 additions and 166 deletions

View File

@@ -578,7 +578,7 @@ pub unsafe extern "C" fn afc_file_read(
}
let fd = unsafe { &mut *(handle as *mut idevice::afc::file::FileDescriptor) };
let res: Result<Vec<u8>, IdeviceError> = run_sync(async move { fd.read().await });
let res: Result<Vec<u8>, IdeviceError> = run_sync(async move { fd.read_entire().await });
match res {
Ok(bytes) => {
@@ -620,7 +620,7 @@ pub unsafe extern "C" fn afc_file_write(
let fd = unsafe { &mut *(handle as *mut idevice::afc::file::FileDescriptor) };
let data_slice = unsafe { std::slice::from_raw_parts(data, length) };
let res: Result<(), IdeviceError> = run_sync(async move { fd.write(data_slice).await });
let res: Result<(), IdeviceError> = run_sync(async move { fd.write_entire(data_slice).await });
match res {
Ok(_) => null_mut(),