1use futures::Stream;
2use rexie::TransactionMode;
3
4use crate::{build_db, inode::Inode, metadata::metadata_from_inode, Metadata, Result};
5use std::{
6 collections::hash_map,
7 ffi::OsString,
8 path::{Path, PathBuf},
9 pin::Pin,
10 task::{Context, Poll},
11};
12
13use crate::FileType;
14
15use super::Dir;
16
17pub struct DirEntry {
18 path: PathBuf,
19 inode: Inode,
20}
21impl DirEntry {
22 pub fn path(&self) -> PathBuf {
23 self.path.clone()
24 }
25
26 pub async fn metadata(&self) -> Result<Metadata> {
27 let rexie = build_db().await?;
28 let transaction = rexie.transaction(&["files"], TransactionMode::ReadOnly)?;
29 metadata_from_inode(&transaction, self.inode, Some(&self.path)).await
30 }
31 pub async fn file_type(&self) -> Result<FileType> {
32 Ok(self.metadata().await?.file_type())
33 }
34 pub fn file_name(&self) -> OsString {
35 self.path.file_name().unwrap().to_os_string()
36 }
37}
38
39pub async fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir> {
40 let rexie = build_db().await?;
41 let transaction = rexie.transaction(&["files"], TransactionMode::ReadWrite)?;
42 let dir = Dir::get_from_path(path.as_ref(), &transaction).await?;
43 Ok(ReadDir {
44 path: path.as_ref().to_path_buf(),
45 children: dir.inner.file_listings.into_iter(),
46 })
47}
48
49pub struct ReadDir {
50 children: hash_map::IntoIter<String, Inode>,
51 path: PathBuf,
52}
53
54impl Stream for ReadDir {
55 type Item = Result<DirEntry>;
56
57 fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
58 fn next(this: &mut ReadDir) -> Option<Result<DirEntry>> {
59 let (name, inode) = this.children.next()?;
60 let mut path = this.path.clone();
61 path.push(name);
62
63 Some(Ok(DirEntry { path, inode }))
64 }
65 Poll::Ready(next(&mut self))
66 }
67}