1use std::future::Future;
2use std::path::Path;
3use std::pin::Pin;
4
5pub trait FileSystem: Clone + Send + Sync + 'static {
10 fn read(
12 &self,
13 path: &Path,
14 ) -> Pin<Box<dyn Future<Output = std::io::Result<Vec<u8>>> + Send + 'static>>;
15
16 fn write(
18 &self,
19 path: &Path,
20 contents: Vec<u8>,
21 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>>;
22
23 fn remove_file(
25 &self,
26 path: &Path,
27 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>>;
28
29 fn create_dir_all(
31 &self,
32 path: &Path,
33 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>>;
34
35 fn exists(&self, path: &Path) -> Pin<Box<dyn Future<Output = bool> + Send + 'static>>;
37}
38
39#[derive(Clone, Default)]
41pub struct TokioFileSystem;
42
43impl FileSystem for TokioFileSystem {
44 fn read(
45 &self,
46 path: &Path,
47 ) -> Pin<Box<dyn Future<Output = std::io::Result<Vec<u8>>> + Send + 'static>> {
48 let p = path.to_path_buf();
49 Box::pin(async move { tokio::fs::read(p).await })
50 }
51
52 fn write(
53 &self,
54 path: &Path,
55 contents: Vec<u8>,
56 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>> {
57 let p = path.to_path_buf();
58 Box::pin(async move { tokio::fs::write(p, contents).await })
59 }
60
61 fn remove_file(
62 &self,
63 path: &Path,
64 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>> {
65 let p = path.to_path_buf();
66 Box::pin(async move { tokio::fs::remove_file(p).await })
67 }
68
69 fn create_dir_all(
70 &self,
71 path: &Path,
72 ) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'static>> {
73 let p = path.to_path_buf();
74 Box::pin(async move { tokio::fs::create_dir_all(p).await })
75 }
76
77 fn exists(&self, path: &Path) -> Pin<Box<dyn Future<Output = bool> + Send + 'static>> {
78 let p = path.to_path_buf();
79 Box::pin(async move { tokio::fs::metadata(p).await.is_ok() })
80 }
81}