seekable_async_file/
common.rs

1use async_trait::async_trait;
2use off64::chrono::Off64AsyncReadChrono;
3use off64::chrono::Off64AsyncWriteChrono;
4use off64::chrono::Off64ReadChrono;
5use off64::chrono::Off64WriteChrono;
6use off64::int::Off64AsyncReadInt;
7use off64::int::Off64AsyncWriteInt;
8use off64::int::Off64ReadInt;
9use off64::int::Off64WriteInt;
10use off64::Off64AsyncRead;
11use off64::Off64AsyncWrite;
12use off64::Off64Read;
13use off64::Off64Write;
14use std::sync::Arc;
15use tokio::task::spawn_blocking;
16
17// It's assumed that a type that implements this can become async optimally by wrapping in Arc and using spawn_blocking.
18// You can use SyncIOAsyncAdapter to wrap a SyncIO in an IAsyncIO.
19// This also allows you to continue using the underlying concrete SyncIO (e.g. mmap raw pointers) or trait methods (e.g. `read_at_sync`) as you can keep an Arc clone.
20pub trait ISyncIO: Send + Sync {
21  fn read_at_sync(&self, offset: u64, len: u64) -> Vec<u8>;
22  fn write_at_sync(&self, offset: u64, data: &[u8]) -> ();
23  fn sync_data_sync(&self) -> ();
24}
25
26impl<'a> Off64Read<'a, Vec<u8>> for dyn ISyncIO {
27  fn read_at(&'a self, offset: u64, len: u64) -> Vec<u8> {
28    self.read_at_sync(offset, len)
29  }
30}
31impl<'a> Off64ReadChrono<'a, Vec<u8>> for dyn ISyncIO {}
32impl<'a> Off64ReadInt<'a, Vec<u8>> for dyn ISyncIO {}
33
34impl Off64Write for dyn ISyncIO {
35  fn write_at(&self, offset: u64, value: &[u8]) -> () {
36    self.write_at_sync(offset, value)
37  }
38}
39impl Off64WriteChrono for dyn ISyncIO {}
40impl Off64WriteInt for dyn ISyncIO {}
41
42#[async_trait]
43pub trait IAsyncIO: for<'a> Off64AsyncRead<'a, Vec<u8>> + Off64AsyncWrite + Send + Sync {
44  async fn sync_data(&self) -> ();
45}
46
47impl<'a> Off64AsyncReadChrono<'a, Vec<u8>> for dyn IAsyncIO {}
48impl<'a> Off64AsyncReadInt<'a, Vec<u8>> for dyn IAsyncIO {}
49
50impl Off64AsyncWriteChrono for dyn IAsyncIO {}
51impl Off64AsyncWriteInt for dyn IAsyncIO {}
52
53pub struct SyncIOAsyncAdapter(Arc<dyn ISyncIO>);
54
55impl SyncIOAsyncAdapter {
56  pub fn new<I: ISyncIO + 'static>(sync_io: Arc<I>) -> Self {
57    Self(sync_io)
58  }
59}
60
61#[async_trait]
62impl<'a> Off64AsyncRead<'a, Vec<u8>> for SyncIOAsyncAdapter {
63  async fn read_at(&self, offset: u64, len: u64) -> Vec<u8> {
64    let io = self.0.clone();
65    spawn_blocking(move || io.read_at_sync(offset, len))
66      .await
67      .unwrap()
68  }
69}
70
71#[async_trait]
72impl Off64AsyncWrite for SyncIOAsyncAdapter {
73  async fn write_at(&self, offset: u64, value: &[u8]) -> () {
74    let io = self.0.clone();
75    let value = value.to_vec();
76    spawn_blocking(move || io.write_at_sync(offset, &value))
77      .await
78      .unwrap()
79  }
80}
81
82#[async_trait]
83impl IAsyncIO for SyncIOAsyncAdapter {
84  async fn sync_data(&self) -> () {
85    let io = self.0.clone();
86    spawn_blocking(move || io.sync_data_sync()).await.unwrap()
87  }
88}