windjammer_runtime/
path.rs1use std::ffi::OsStr;
7use std::path::{Path as StdPath, PathBuf as StdPathBuf};
8
9pub use std::path::Path;
11
12pub use std::path::PathBuf;
14
15pub fn new(s: &str) -> &StdPath {
17 StdPath::new(s)
18}
19
20pub fn from_str(s: &str) -> StdPathBuf {
22 StdPathBuf::from(s)
23}
24
25pub fn file_name(path: &StdPath) -> Option<&str> {
27 path.file_name().and_then(|s| s.to_str())
28}
29
30pub fn file_stem(path: &StdPath) -> Option<&str> {
32 path.file_stem().and_then(|s| s.to_str())
33}
34
35pub fn extension<P: AsRef<StdPath>>(path: P) -> Option<String> {
37 path.as_ref()
38 .extension()
39 .and_then(|s| s.to_str())
40 .map(|s| s.to_string())
41}
42
43pub fn parent(path: &StdPath) -> Option<&StdPath> {
45 path.parent()
46}
47
48pub fn is_absolute(path: &StdPath) -> bool {
50 path.is_absolute()
51}
52
53pub fn is_relative(path: &StdPath) -> bool {
55 path.is_relative()
56}
57
58pub fn exists(path: &StdPath) -> bool {
60 path.exists()
61}
62
63pub fn is_file(path: &StdPath) -> bool {
65 path.is_file()
66}
67
68pub fn is_dir(path: &StdPath) -> bool {
70 path.is_dir()
71}
72
73pub fn join(path: &StdPath, other: &str) -> StdPathBuf {
75 path.join(other)
76}
77
78pub fn to_string(path: &StdPath) -> Option<String> {
80 path.to_str().map(String::from)
81}
82
83pub fn to_string_lossy(path: &StdPath) -> String {
85 path.to_string_lossy().into_owned()
86}
87
88pub fn components(path: &StdPath) -> Vec<String> {
90 path.components()
91 .filter_map(|c| c.as_os_str().to_str())
92 .map(String::from)
93 .collect()
94}
95
96pub fn canonicalize(path: &StdPath) -> Result<StdPathBuf, String> {
98 path.canonicalize()
99 .map_err(|e| format!("Failed to canonicalize path: {}", e))
100}
101
102pub fn current_dir() -> Result<StdPathBuf, String> {
104 std::env::current_dir().map_err(|e| format!("Failed to get current directory: {}", e))
105}
106
107pub fn has_extension(path: &StdPath, ext: &str) -> bool {
109 path.extension()
110 .and_then(|e| e.to_str())
111 .map(|e| e == ext)
112 .unwrap_or(false)
113}
114
115pub fn strip_prefix<'a>(path: &'a StdPath, prefix: &StdPath) -> Option<&'a StdPath> {
117 path.strip_prefix(prefix).ok()
118}
119
120pub fn as_os_str(path: &StdPath) -> &OsStr {
122 path.as_os_str()
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_path_operations() {
131 let path = new("/foo/bar/baz.txt");
132
133 assert_eq!(file_name(path), Some("baz.txt"));
134 assert_eq!(file_stem(path), Some("baz"));
135 assert_eq!(extension(path), Some("txt".to_string()));
136 assert!(is_absolute(path));
137
138 let relative = new("foo/bar.txt");
139 assert!(is_relative(relative));
140 }
141
142 #[test]
143 fn test_path_join() {
144 let base = new("/foo");
145 let joined = join(base, "bar");
146 assert_eq!(to_string(&joined), Some("/foo/bar".to_string()));
147 }
148
149 #[test]
150 fn test_extension_check() {
151 let path = new("file.wj");
152 assert!(has_extension(path, "wj"));
153 assert!(!has_extension(path, "rs"));
154 }
155}