dir_structure/vfs/
fs_vfs.rs1use std::fs;
6use std::path::Path;
7use std::path::PathBuf;
8use std::pin::Pin;
9
10use crate::error::Result;
11use crate::error::VfsResult;
12use crate::error::WrapIoError;
13use crate::traits::vfs::DirEntryInfo;
14use crate::traits::vfs::DirEntryKind;
15use crate::traits::vfs::DirWalker;
16use crate::traits::vfs::PathType;
17use crate::traits::vfs::Vfs;
18use crate::traits::vfs::VfsCore;
19use crate::traits::vfs::WriteSupportingVfs;
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
23pub struct FsVfs;
24
25impl VfsCore for FsVfs {
26 type Path = Path;
27}
28
29impl<'a> Vfs<'a> for FsVfs {
30 type DirWalk<'b>
31 = imp::FsDirWalker
32 where
33 'a: 'b,
34 Self: 'b;
35
36 type RFile = fs::File;
37
38 fn open_read(self: Pin<&Self>, path: &Self::Path) -> VfsResult<Self::RFile, Self> {
39 fs::File::open(path).wrap_io_error_with(path)
40 }
41
42 fn read(self: Pin<&Self>, path: &Self::Path) -> VfsResult<Vec<u8>, Self> {
43 fs::read(path).wrap_io_error_with(path)
44 }
45
46 fn read_string(self: Pin<&Self>, path: &Self::Path) -> VfsResult<String, Self> {
47 fs::read_to_string(path).wrap_io_error_with(path)
48 }
49
50 fn exists(self: Pin<&Self>, path: &Self::Path) -> VfsResult<bool, Self> {
51 Ok(path.exists())
52 }
53
54 fn is_dir(self: Pin<&Self>, path: &Self::Path) -> VfsResult<bool, Self> {
55 Ok(path.is_dir())
56 }
57
58 fn walk_dir<'b>(self: Pin<&'b Self>, path: &Self::Path) -> VfsResult<Self::DirWalk<'b>, Self>
59 where
60 'a: 'b,
61 {
62 fs::read_dir(path)
63 .wrap_io_error_with(path)
64 .map(|read_dir| imp::FsDirWalker(read_dir, path.to_path_buf()))
65 }
66}
67
68impl<'a> WriteSupportingVfs<'a> for FsVfs {
69 type WFile = fs::File;
70
71 fn open_write(self: Pin<&Self>, path: &Self::Path) -> VfsResult<Self::WFile, Self> {
72 fs::File::create(path).wrap_io_error_with(path)
73 }
74
75 fn write(self: Pin<&Self>, path: &Self::Path, data: &[u8]) -> VfsResult<(), Self> {
76 fs::write(path, data).wrap_io_error_with(path)
77 }
78
79 fn create_dir(self: Pin<&Self>, path: &Self::Path) -> VfsResult<(), Self> {
80 fs::create_dir(path).wrap_io_error_with(path)
81 }
82
83 fn create_dir_all(self: Pin<&Self>, path: &Self::Path) -> VfsResult<(), Self> {
84 fs::create_dir_all(path).wrap_io_error_with(path)
85 }
86
87 fn remove_dir_all(self: Pin<&Self>, path: &Self::Path) -> VfsResult<(), Self> {
88 fs::remove_dir_all(path).wrap_io_error_with(path)
89 }
90
91 fn create_parent_dir(self: Pin<&Self>, path: &Self::Path) -> VfsResult<(), Self> {
92 if let Some(parent) = path.parent()
93 && !self.exists(parent)?
94 {
95 self.create_dir_all(parent)?;
96 }
97 Ok(())
98 }
99}
100
101mod imp {
102 use std::io;
103
104 use super::*;
105
106 pub struct FsDirWalker(pub(super) fs::ReadDir, pub(super) PathBuf);
108
109 impl<'a> DirWalker<'a> for FsDirWalker {
110 type P = Path;
111
112 fn next(
113 &mut self,
114 ) -> Option<Result<DirEntryInfo<Self::P>, <Self::P as PathType>::OwnedPath>> {
115 self.0.next().map(|entry| {
116 <io::Result<_> as WrapIoError<Self::P>>::wrap_io_error(
117 entry.and_then(|e| {
118 Ok(DirEntryInfo {
119 name: e.file_name(),
120 path: e.path(),
121 kind: if e.file_type()?.is_dir() {
122 DirEntryKind::Directory
123 } else {
124 DirEntryKind::File
125 },
126 })
127 }),
128 || self.1.clone(),
129 )
130 })
131 }
132 }
133}