Skip to main content

dolang_vfs/directory/
mod.rs

1use crate::{client, direct, error::Result, metadata::FileType};
2use serde::{Deserialize, Serialize};
3
4/// An entry returned by [`ReadDir`].
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub struct DirEntry {
7    file_name: String,
8    file_type: FileType,
9    family: DirEntryFamily,
10}
11
12/// Platform-specific fields carried by a directory entry.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub(crate) enum DirEntryFamily {
15    /// Unix-specific entry information.
16    Unix { ino: u64 },
17    /// Windows entry information.
18    Windows,
19}
20
21impl DirEntry {
22    pub(crate) fn new(file_name: String, file_type: FileType, family: DirEntryFamily) -> Self {
23        Self {
24            file_name,
25            file_type,
26            family,
27        }
28    }
29
30    /// Returns the entry name without its parent path.
31    pub fn file_name(&self) -> &std::ffi::OsStr {
32        std::ffi::OsStr::new(&self.file_name)
33    }
34
35    /// Returns the inode number when the target is Unix-like.
36    pub fn ino(&self) -> Option<u64> {
37        match self.family {
38            DirEntryFamily::Unix { ino } => Some(ino),
39            DirEntryFamily::Windows => None,
40        }
41    }
42
43    /// Returns the entry's file type.
44    pub fn file_type(&self) -> FileType {
45        self.file_type
46    }
47}
48
49#[derive(Debug)]
50enum ReadDirInner {
51    Client(client::ReadDir),
52    Direct(direct::ReadDir),
53}
54
55/// An asynchronous directory iterator.
56#[derive(Debug)]
57pub struct ReadDir {
58    inner: ReadDirInner,
59}
60
61impl ReadDir {
62    pub(crate) fn client(read_dir: client::ReadDir) -> Self {
63        Self {
64            inner: ReadDirInner::Client(read_dir),
65        }
66    }
67
68    pub(crate) fn direct(read_dir: direct::ReadDir) -> Self {
69        Self {
70            inner: ReadDirInner::Direct(read_dir),
71        }
72    }
73
74    /// Returns the next directory entry, or `None` after the iterator is exhausted.
75    pub async fn next_entry(&mut self) -> Result<Option<DirEntry>> {
76        Ok(match &mut self.inner {
77            ReadDirInner::Client(read_dir) => read_dir.next_entry().await?,
78            ReadDirInner::Direct(read_dir) => read_dir.next_entry().await?,
79        })
80    }
81}