1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use crate::{OpenOptions, VFile, VMetadata, Vfs, VfsResult}; use async_std::{fs, path::PathBuf}; use async_trait::async_trait; pub struct OsFs { root: PathBuf, } struct VOsMetadata { path: PathBuf, is_file: bool, len: u64, } impl OsFs { pub fn new(root: &str) -> Self { OsFs { root: PathBuf::from(root), } } fn get_path(&self, path: &str) -> PathBuf { let p = if path.starts_with('/') { &path[1..] } else { path }; self.root.join(p) } } impl VMetadata for VOsMetadata { fn name(&self) -> &str { self.path.to_str().unwrap() } fn is_dir(&self) -> bool { !self.is_file } fn is_file(&self) -> bool { self.is_file } fn len(&self) -> u64 { self.len } } #[async_trait] impl Vfs for OsFs { async fn exists(&self, path: &str) -> VfsResult<bool> { Ok(self.get_path(path).exists().await) } async fn metadata(&self, path: &str) -> VfsResult<Box<dyn VMetadata>> { let path = self.get_path(path); let metadata = path.metadata().await?; let vmetadata = if metadata.is_dir() { VOsMetadata { is_file: false, len: 0, path, } } else { VOsMetadata { is_file: true, len: metadata.len(), path, } }; Ok(Box::new(vmetadata)) } async fn mkdir(&self, path: &str) -> VfsResult<()> { Ok(fs::create_dir(self.get_path(path)).await?) } async fn mv(&self, from: &str, to: &str) -> VfsResult<()> { Ok(fs::rename(from, to).await?) } async fn open(&self, path: &str, options: OpenOptions) -> VfsResult<Box<dyn VFile>> { let file = fs::OpenOptions::new() .read(options.has_read()) .write(options.has_write()) .create(options.has_create()) .append(options.has_append()) .truncate(options.has_truncate()) .open(self.get_path(path)) .await?; Ok(Box::new(file)) } async fn read_dir( &self, path: &str, skip_token: Option<String>, ) -> VfsResult<(Vec<Box<dyn VMetadata>>, Option<String>)> { todo!() } async fn rm(&self, path: &str) -> VfsResult<()> { let path = self.get_path(path); let metadata = path.metadata().await?; if metadata.is_dir() { Ok(fs::remove_dir(path).await?) } else { Ok(fs::remove_file(path).await?) } } }