#![cfg_attr(not(feature = "std"), no_std)]
use crate::error::Errno;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
pub trait IoBuf {
fn len(&self) -> usize {
self.as_slice().len()
}
fn as_slice(&self) -> &[u8];
}
pub trait IoBufMut: IoBuf {
fn as_mut_slice(&mut self) -> &mut [u8];
}
pub type IoResult = Result<(), Errno>;
pub type Completion = Box<dyn FnOnce(IoResult) + Send + 'static>;
pub trait BlockAsyncIo: Send + Sync + 'static {
fn block_size(&self) -> usize;
fn read(&self, block: u64, buf: &mut [u8], completion: Completion);
fn write(&self, block: u64, buf: &[u8], completion: Completion);
fn flush(&self, completion: Completion) {
completion(Ok(()));
}
}
#[cfg(feature = "tokio")]
mod ext {
use super::{BlockAsyncIo, IoResult};
use crate::error::Errno;
use std::sync::Arc;
pub trait BlockAsyncIoExt: BlockAsyncIo + Sized {
async fn read_async(&self, block: u64, buf: &mut [u8]) -> IoResult {
let (tx, rx) = tokio::sync::oneshot::channel();
self.read(
block,
buf,
Box::new(move |res| {
let _ = tx.send(res);
}),
);
rx.await.unwrap_or(Err(Errno::Unknown))
}
async fn write_async(&self, block: u64, buf: &[u8]) -> IoResult {
let (tx, rx) = tokio::sync::oneshot::channel();
self.write(
block,
buf,
Box::new(move |res| {
let _ = tx.send(res);
}),
);
rx.await.unwrap_or(Err(Errno::Unknown))
}
async fn flush_async(&self) -> IoResult {
let (tx, rx) = tokio::sync::oneshot::channel();
self.flush(Box::new(move |res| {
let _ = tx.send(res);
}));
rx.await.unwrap_or(Err(Errno::Unknown))
}
fn into_arc(self) -> Arc<Self>
where
Self: Sized,
{
Arc::new(self)
}
}
impl<T: BlockAsyncIo> BlockAsyncIoExt for T {}
pub use BlockAsyncIoExt as _; }
#[cfg(feature = "tokio")]
pub use ext::*;