1use core::fmt::Debug;
2use core::slice::Iter;
3use std::borrow::ToOwned;
4use std::format;
5use std::path::{Path, PathBuf};
6
7use alloc::boxed::Box;
8use alloc::string::String;
9use alloc::vec::Vec;
10
11use crate::blockdev::BlockDeviceWrite;
12
13use maybe_async::maybe_async;
14
15mod remap;
16mod sector_linear;
17mod xdvdfs;
18
19pub use remap::*;
20pub use sector_linear::*;
21pub use xdvdfs::*;
22
23#[cfg(not(target_family = "wasm"))]
24mod stdfs;
25
26#[cfg(not(target_family = "wasm"))]
27pub use stdfs::*;
28
29#[derive(Copy, Clone, Debug)]
30pub enum FileType {
31 File,
32 Directory,
33}
34
35#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
36pub struct PathVec {
37 components: Vec<String>,
38}
39
40type PathVecIter<'a> = Iter<'a, String>;
41
42#[derive(Clone, Debug)]
43pub struct FileEntry {
44 pub name: String,
45 pub file_type: FileType,
46 pub len: u64,
47}
48
49#[derive(Clone, Debug)]
50pub struct DirectoryTreeEntry {
51 pub dir: PathVec,
52 pub listing: Vec<FileEntry>,
53}
54
55impl PathVec {
56 pub fn as_path_buf(&self, prefix: &Path) -> PathBuf {
57 let suffix = PathBuf::from_iter(self.components.iter());
58 prefix.join(suffix)
59 }
60
61 pub fn is_root(&self) -> bool {
62 self.components.is_empty()
63 }
64
65 pub fn iter(&self) -> PathVecIter {
66 self.components.iter()
67 }
68
69 pub fn from_base(prefix: &Self, suffix: &str) -> Self {
70 let mut path = prefix.clone();
71 path.components.push(suffix.to_owned());
72 path
73 }
74
75 pub fn as_string(&self) -> String {
76 format!("/{}", self.components.join("/"))
77 }
78
79 pub fn suffix(&self, prefix: &Self) -> Self {
80 let mut components = Vec::new();
81 let mut i1 = self.iter();
82 let mut i2 = prefix.iter();
83
84 loop {
85 let c1 = i1.next();
86 let c2 = i2.next();
87
88 if let Some(component) = c1 {
89 if let Some(component2) = c2 {
90 assert_eq!(component, component2);
91 } else {
92 components.push(component.clone());
93 }
94 } else {
95 return Self { components };
96 }
97 }
98 }
99}
100
101impl<'a> FromIterator<&'a str> for PathVec {
102 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
103 let components = iter
104 .into_iter()
105 .filter(|s| !s.is_empty())
106 .map(|s| s.to_owned())
107 .collect();
108 Self { components }
109 }
110}
111
112#[maybe_async]
113pub trait Filesystem<RawHandle: BlockDeviceWrite<RHError>, E, RHError: Into<E> = E>:
114 Send + Sync
115{
116 async fn read_dir(&mut self, path: &PathVec) -> Result<Vec<FileEntry>, E>;
121
122 async fn copy_file_in(
124 &mut self,
125 src: &PathVec,
126 dest: &mut RawHandle,
127 offset: u64,
128 size: u64,
129 ) -> Result<u64, E>;
130
131 async fn copy_file_buf(
134 &mut self,
135 _src: &PathVec,
136 _buf: &mut [u8],
137 _offset: u64,
138 ) -> Result<u64, E>;
139
140 fn path_to_string(&self, path: &PathVec) -> String {
142 path.as_string()
143 }
144}
145
146#[maybe_async]
147impl<E: Send + Sync, R: BlockDeviceWrite<E>> Filesystem<R, E> for Box<dyn Filesystem<R, E>> {
148 async fn read_dir(&mut self, path: &PathVec) -> Result<Vec<FileEntry>, E> {
149 self.as_mut().read_dir(path).await
150 }
151
152 async fn copy_file_in(
153 &mut self,
154 src: &PathVec,
155 dest: &mut R,
156 offset: u64,
157 size: u64,
158 ) -> Result<u64, E> {
159 self.as_mut().copy_file_in(src, dest, offset, size).await
160 }
161
162 async fn copy_file_buf(
163 &mut self,
164 src: &PathVec,
165 buf: &mut [u8],
166 offset: u64,
167 ) -> Result<u64, E> {
168 self.as_mut().copy_file_buf(src, buf, offset).await
169 }
170}