Skip to main content

dear_file_browser/
fs.rs

1use std::path::{Path, PathBuf};
2
3/// Minimal file metadata used by the in-UI file browser.
4#[derive(Clone, Debug)]
5pub struct FsMetadata {
6    /// Whether the path refers to a directory.
7    pub is_dir: bool,
8    /// Whether the path itself is a symbolic link.
9    pub is_symlink: bool,
10}
11
12/// Directory entry returned by [`FileSystem::read_dir`].
13#[derive(Clone, Debug)]
14pub struct FsEntry {
15    /// Base name (no parent path)
16    pub name: String,
17    /// Full path
18    pub path: PathBuf,
19    /// Whether this entry is a directory.
20    pub is_dir: bool,
21    /// Whether this entry itself is a symbolic link.
22    pub is_symlink: bool,
23    /// File size in bytes (files and file-links only; `None` for directories or when unavailable).
24    pub size: Option<u64>,
25    /// Last modified timestamp (when available).
26    pub modified: Option<std::time::SystemTime>,
27}
28
29/// File system abstraction (IGFD `IFileSystem`-like).
30///
31/// This is a first incremental step; the API will expand as Places/devices,
32/// directory creation, symlink support, and async enumeration are added.
33pub trait FileSystem {
34    /// List entries of a directory.
35    fn read_dir(&self, dir: &Path) -> std::io::Result<Vec<FsEntry>>;
36    /// Canonicalize a path (best-effort absolute normalization).
37    fn canonicalize(&self, path: &Path) -> std::io::Result<PathBuf>;
38    /// Fetch minimal metadata for a path.
39    fn metadata(&self, path: &Path) -> std::io::Result<FsMetadata>;
40    /// Create a directory.
41    fn create_dir(&self, path: &Path) -> std::io::Result<()>;
42    /// Rename/move a path.
43    fn rename(&self, from: &Path, to: &Path) -> std::io::Result<()>;
44    /// Remove a file.
45    fn remove_file(&self, path: &Path) -> std::io::Result<()>;
46    /// Remove an empty directory.
47    fn remove_dir(&self, path: &Path) -> std::io::Result<()>;
48    /// Remove a directory and all of its contents (recursive).
49    fn remove_dir_all(&self, path: &Path) -> std::io::Result<()>;
50    /// Copy a file.
51    ///
52    /// Returns the number of bytes copied (mirrors `std::fs::copy`).
53    fn copy_file(&self, from: &Path, to: &Path) -> std::io::Result<u64>;
54}
55
56/// Default filesystem implementation using `std::fs`.
57#[derive(Clone, Copy, Debug, Default)]
58pub struct StdFileSystem;
59
60impl FileSystem for StdFileSystem {
61    fn read_dir(&self, dir: &Path) -> std::io::Result<Vec<FsEntry>> {
62        let mut out = Vec::new();
63        let rd = std::fs::read_dir(dir)?;
64        for e in rd {
65            let e = match e {
66                Ok(v) => v,
67                Err(_) => continue,
68            };
69            let ft = match e.file_type() {
70                Ok(v) => v,
71                Err(_) => continue,
72            };
73            let name = e.file_name().to_string_lossy().to_string();
74            let path = e.path();
75            let meta = e.metadata().ok();
76            let modified = meta.as_ref().and_then(|m| m.modified().ok());
77            let is_dir = ft.is_dir();
78            let is_symlink = ft.is_symlink();
79            let size = if is_dir {
80                None
81            } else {
82                meta.as_ref().filter(|m| m.is_file()).map(|m| m.len())
83            };
84            out.push(FsEntry {
85                name,
86                path,
87                is_dir,
88                is_symlink,
89                size,
90                modified,
91            });
92        }
93        Ok(out)
94    }
95
96    fn canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> {
97        std::fs::canonicalize(path)
98    }
99
100    fn metadata(&self, path: &Path) -> std::io::Result<FsMetadata> {
101        let md = std::fs::metadata(path)?;
102        let link_md = std::fs::symlink_metadata(path)?;
103        Ok(FsMetadata {
104            is_dir: md.is_dir(),
105            is_symlink: link_md.file_type().is_symlink(),
106        })
107    }
108
109    fn create_dir(&self, path: &Path) -> std::io::Result<()> {
110        std::fs::create_dir(path)
111    }
112
113    fn rename(&self, from: &Path, to: &Path) -> std::io::Result<()> {
114        std::fs::rename(from, to)
115    }
116
117    fn remove_file(&self, path: &Path) -> std::io::Result<()> {
118        std::fs::remove_file(path)
119    }
120
121    fn remove_dir(&self, path: &Path) -> std::io::Result<()> {
122        std::fs::remove_dir(path)
123    }
124
125    fn remove_dir_all(&self, path: &Path) -> std::io::Result<()> {
126        std::fs::remove_dir_all(path)
127    }
128
129    fn copy_file(&self, from: &Path, to: &Path) -> std::io::Result<u64> {
130        std::fs::copy(from, to)
131    }
132}