tokio_fs_ext/fs/wasm/
read_dir.rs1use std::{
2 ffi::OsString,
3 fmt::Debug,
4 io,
5 path::{Path, PathBuf},
6 str::FromStr,
7 task::{Context, Poll},
8};
9
10use futures::{TryStreamExt, stream::StreamExt};
11use js_sys::{Array, JsString};
12use wasm_bindgen::JsCast;
13use wasm_bindgen_futures::stream::JsStream;
14use web_sys::FileSystemHandle;
15
16use super::{
17 metadata::{FileType, Metadata},
18 opfs::{OpfsError, open_dir},
19};
20
21pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> {
22 let dir_handle = open_dir(&path, super::opfs::OpenDirType::NotCreate).await?;
23 let entries = JsStream::from(dir_handle.entries())
24 .map(|handle| {
25 handle.map_or_else(
26 |err| Err(OpfsError::from(err).into_io_err()),
27 |entry| {
28 Ok({
29 let js_array = Array::from(&entry);
30
31 let name = OsString::from_str(
32 JsString::from(js_array.get(0))
33 .as_string()
34 .ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?
35 .as_str(),
36 )
37 .map_err(|_| io::Error::from(io::ErrorKind::InvalidFilename))?;
38
39 let path = path.as_ref().join(&name);
40
41 let file_type = js_array
42 .get(1)
43 .unchecked_into::<FileSystemHandle>()
44 .kind()
45 .into();
46
47 DirEntry {
48 file_type,
49 path,
50 name,
51 }
52 })
53 },
54 )
55 })
56 .try_collect()
57 .await?;
58
59 Ok(ReadDir { entries })
60}
61
62#[derive(Debug)]
63pub struct ReadDir {
64 entries: Vec<DirEntry>,
65}
66
67impl ReadDir {
68 pub async fn next_entry(&mut self) -> io::Result<Option<DirEntry>> {
69 Ok(self.entries.pop())
70 }
71
72 pub fn poll_next_entry(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> {
73 Poll::Ready(Ok(self.entries.pop()))
74 }
75}
76
77impl Iterator for ReadDir {
78 type Item = io::Result<DirEntry>;
79
80 fn next(&mut self) -> Option<io::Result<DirEntry>> {
81 self.entries.pop().map(Result::Ok)
82 }
83}
84
85impl FromIterator<DirEntry> for ReadDir {
86 fn from_iter<T: IntoIterator<Item = DirEntry>>(iter: T) -> Self {
87 ReadDir {
88 entries: iter.into_iter().collect(),
89 }
90 }
91}
92
93#[derive(Debug)]
94pub struct DirEntry {
95 file_type: FileType,
96 name: OsString,
97 path: PathBuf,
98}
99
100impl DirEntry {
101 pub fn new(path: PathBuf, name: OsString, file_type: FileType) -> Self {
105 Self {
106 file_type,
107 name,
108 path,
109 }
110 }
111
112 pub fn path(&self) -> PathBuf {
113 self.path.clone()
114 }
115
116 pub fn file_name(&self) -> OsString {
117 self.name.clone()
118 }
119
120 pub fn file_type(&self) -> io::Result<FileType> {
121 Ok(self.file_type)
122 }
123
124 pub async fn metadata(&self) -> io::Result<Metadata> {
125 todo!()
126 }
127}