tokio_fs_ext/fs/wasm/
metadata.rs

1use std::{io, path::Path};
2
3use web_sys::FileSystemHandleKind;
4
5use super::opfs::{OpfsError, open_dir, open_file};
6
7/// Symlink is not supported.
8#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
9pub enum FileType {
10    #[default]
11    File,
12    Directory,
13    // TODO:
14    Symlink,
15}
16
17impl FileType {
18    pub fn is_dir(&self) -> bool {
19        *self == Self::Directory
20    }
21
22    pub fn is_file(&self) -> bool {
23        *self == Self::File
24    }
25
26    pub fn is_symlink(&self) -> bool {
27        *self == Self::Symlink
28    }
29}
30
31impl From<&FileSystemHandleKind> for FileType {
32    fn from(handle: &FileSystemHandleKind) -> Self {
33        match handle {
34            FileSystemHandleKind::File => FileType::File,
35            FileSystemHandleKind::Directory => FileType::Directory,
36            _ => todo!(),
37        }
38    }
39}
40
41impl From<FileSystemHandleKind> for FileType {
42    fn from(handle: FileSystemHandleKind) -> Self {
43        (&handle).into()
44    }
45}
46
47#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
48pub struct Metadata {
49    pub(crate) file_type: FileType,
50    pub(crate) file_size: u64,
51}
52
53impl Metadata {
54    pub fn new(file_type: FileType, file_size: u64) -> Self {
55        Self {
56            file_type,
57            file_size,
58        }
59    }
60}
61
62impl Metadata {
63    pub fn is_dir(&self) -> bool {
64        self.file_type.is_dir()
65    }
66
67    pub fn is_file(&self) -> bool {
68        self.file_type.is_file()
69    }
70
71    pub fn is_symlink(&self) -> bool {
72        self.file_type.is_symlink()
73    }
74
75    #[allow(clippy::len_without_is_empty)]
76    pub fn len(&self) -> u64 {
77        self.file_size
78    }
79}
80
81pub async fn metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
82    match open_file(
83        &path,
84        super::opfs::CreateFileMode::NotCreate,
85        super::opfs::SyncAccessMode::Readonly,
86        false,
87    )
88    .await
89    {
90        Ok(file) => {
91            let len = file
92                .sync_access_handle
93                .get_size()
94                .map_err(|err| OpfsError::from(err).into_io_err())? as u64;
95            Ok(Metadata {
96                file_type: FileType::File,
97                file_size: len,
98            })
99        }
100        Err(_) => Ok(open_dir(path, super::opfs::OpenDirType::NotCreate)
101            .await
102            .map(|_| Metadata {
103                file_type: FileType::Directory,
104                file_size: 0,
105            })?),
106    }
107}