Skip to main content

windjammer_runtime/
fs.rs

1//! File system operations
2//!
3//! Windjammer's `std::fs` module maps to these functions.
4
5use std::path::Path;
6
7/// Read entire file as a string
8pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String, String> {
9    std::fs::read_to_string(path).map_err(|e| e.to_string())
10}
11
12/// Read entire file as bytes
13pub fn read<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, String> {
14    std::fs::read(path).map_err(|e| e.to_string())
15}
16
17/// Alias for read() for clarity  
18pub fn read_bytes<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, String> {
19    read(path)
20}
21
22/// Write to file (accepts bytes or strings)
23pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<(), String> {
24    std::fs::write(path, contents).map_err(|e| e.to_string())
25}
26
27/// Write string to file (helper for common case)
28pub fn write_string<P: AsRef<Path>>(path: P, contents: &str) -> Result<(), String> {
29    write(path, contents.as_bytes())
30}
31
32/// Check if path exists
33pub fn exists<P: AsRef<Path>>(path: P) -> bool {
34    path.as_ref().exists()
35}
36
37/// Check if path is a file
38pub fn is_file<P: AsRef<Path>>(path: P) -> bool {
39    path.as_ref().is_file()
40}
41
42/// Check if path is a directory
43pub fn is_dir<P: AsRef<Path>>(path: P) -> bool {
44    path.as_ref().is_dir()
45}
46
47/// Create a directory
48pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
49    std::fs::create_dir(path).map_err(|e| e.to_string())
50}
51
52/// Create a directory and all parent directories
53pub fn create_dir_all<P: AsRef<Path>>(path: P) -> Result<(), String> {
54    std::fs::create_dir_all(path).map_err(|e| e.to_string())
55}
56
57/// Remove a file
58pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<(), String> {
59    std::fs::remove_file(path).map_err(|e| e.to_string())
60}
61
62/// Remove a directory
63pub fn remove_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
64    std::fs::remove_dir(path).map_err(|e| e.to_string())
65}
66
67/// Remove a directory and all its contents
68pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> Result<(), String> {
69    std::fs::remove_dir_all(path).map_err(|e| e.to_string())
70}
71
72/// Copy a file
73pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64, String> {
74    std::fs::copy(from, to).map_err(|e| e.to_string())
75}
76
77/// Rename a file or directory
78pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<(), String> {
79    std::fs::rename(from, to).map_err(|e| e.to_string())
80}
81
82/// Directory entry wrapper
83#[derive(Debug, Clone)]
84pub struct DirEntry {
85    path: String,
86}
87
88impl DirEntry {
89    /// Get the full path to this entry
90    pub fn path(&self) -> String {
91        self.path.clone()
92    }
93
94    /// Get the file name (last component of path)
95    pub fn file_name(&self) -> String {
96        Path::new(&self.path)
97            .file_name()
98            .and_then(|n| n.to_str())
99            .unwrap_or("")
100            .to_string()
101    }
102
103    /// Check if this entry is a file
104    pub fn is_file(&self) -> bool {
105        Path::new(&self.path).is_file()
106    }
107
108    /// Check if this entry is a directory
109    pub fn is_dir(&self) -> bool {
110        Path::new(&self.path).is_dir()
111    }
112}
113
114/// List directory entries
115pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<Vec<DirEntry>, String> {
116    let entries = std::fs::read_dir(path).map_err(|e| e.to_string())?;
117    let mut result = Vec::new();
118    for entry in entries {
119        let entry = entry.map_err(|e| e.to_string())?;
120        let path = entry.path();
121        if let Some(path_str) = path.to_str() {
122            result.push(DirEntry {
123                path: path_str.to_string(),
124            });
125        }
126    }
127    Ok(result)
128}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[test]
135    fn test_read_write() {
136        let temp = std::env::temp_dir().join("windjammer_test.txt");
137        let content = "Hello, Windjammer!";
138
139        write(&temp, content).unwrap();
140        let read_content = read_to_string(&temp).unwrap();
141
142        assert_eq!(content, read_content);
143        remove_file(&temp).unwrap();
144    }
145
146    #[test]
147    fn test_exists() {
148        let temp = std::env::temp_dir().join("windjammer_exists_test.txt");
149
150        assert!(!exists(&temp));
151        write(&temp, "test").unwrap();
152        assert!(exists(&temp));
153        assert!(is_file(&temp));
154        assert!(!is_dir(&temp));
155
156        remove_file(&temp).unwrap();
157    }
158}