Skip to main content

idbfs/dir/
direntry.rs

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}