Skip to main content

pathkit/
traits.rs

1use std::{
2    borrow::Borrow,
3    fmt::{
4        Display,
5        Formatter,
6        Result as FmtResult,
7    },
8    ops::Deref,
9    path::{
10        Path as StdPath,
11        PathBuf,
12    },
13};
14
15use super::core::Path;
16
17impl AsRef<StdPath> for Path {
18    fn as_ref(&self) -> &StdPath {
19        &self.0
20    }
21}
22
23impl Borrow<StdPath> for Path {
24    fn borrow(&self) -> &StdPath {
25        &self.0
26    }
27}
28
29impl Deref for Path {
30    type Target = StdPath;
31
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl Display for Path {
38    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
39        write!(f, "{}", self.to_string_lossy())
40    }
41}
42
43impl From<&StdPath> for Path {
44    fn from(path: &StdPath) -> Self {
45        Self(path.to_path_buf())
46    }
47}
48
49impl From<Path> for PathBuf {
50    fn from(path: Path) -> Self {
51        path.0
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use std::{
58        borrow::Borrow,
59        ops::Deref,
60        path::{
61            Path as StdPath,
62            PathBuf,
63        },
64    };
65
66    use super::Path;
67
68    // Test AsRef<StdPath>
69    #[test]
70    fn test_as_ref_std_path() {
71        let path = Path::new("/test/path");
72        let std_path: &StdPath = path.as_ref();
73        assert_eq!(std_path, StdPath::new("/test/path"));
74    }
75
76    // Test AsRef<Path> - check that as_ref returns the path through deref
77    #[test]
78    fn test_as_ref_self() {
79        let path = Path::new("/test/path");
80        // as_ref returns &StdPath through Deref
81        let path_ref = path.as_ref();
82        assert_eq!(path_ref, StdPath::new("/test/path"));
83    }
84
85    // Test Borrow<StdPath>
86    #[test]
87    fn test_borrow() {
88        let path = Path::new("/test/path");
89        let borrowed: &StdPath = path.borrow();
90        assert_eq!(borrowed, StdPath::new("/test/path"));
91    }
92
93    // Test Deref
94    #[test]
95    fn test_deref() {
96        let path = Path::new("/test/path");
97        let dereferenced: &StdPath = path.deref();
98        assert_eq!(dereferenced, StdPath::new("/test/path"));
99    }
100
101    // Skip Deref target test - Path::target doesn't exist
102    // Test Display
103    #[test]
104    fn test_display() {
105        let path = Path::new("/test/path");
106        let display: String = path.to_string();
107        assert_eq!(display, "/test/path");
108    }
109
110    // Test Display format
111    #[test]
112    fn test_display_format() {
113        let path = Path::new("/test/path");
114        assert_eq!(format!("{}", path), "/test/path");
115    }
116
117    // Test Display with other format specifiers
118    #[test]
119    fn test_display_format_args() {
120        let path = Path::new("file.txt");
121        assert_eq!(format!("Path: {}", path), "Path: file.txt");
122    }
123
124    // Test From<&StdPath> for Path
125    #[test]
126    fn test_from_std_path_ref() {
127        let std_path = std::path::Path::new("/test/path");
128        let path: Path = Path::from(std_path);
129        assert_eq!(path.to_str(), Some("/test/path"));
130    }
131
132    // Test From<PathBuf> for Path - use Path::new instead
133    #[test]
134    fn test_from_pathbuf() {
135        let pathbuf = PathBuf::from("/test/path");
136        let path = Path::new(pathbuf);
137        assert_eq!(path.to_path_buf(), PathBuf::from("/test/path"));
138    }
139
140    // Test From<Path> for PathBuf
141    #[test]
142    fn test_from_path_to_pathbuf() {
143        let path = Path::new("/test/path");
144        let pathbuf: PathBuf = PathBuf::from(path);
145        assert_eq!(pathbuf, PathBuf::from("/test/path"));
146    }
147
148    // Skip test_from_string - Path doesn't implement From<String>
149    // Skip test_from_str - Path doesn't implement From<&str>
150
151    // Test to_string_lossy
152    #[test]
153    fn test_to_string_lossy() {
154        let path = Path::new("/test/path");
155        let lost = path.to_string_lossy();
156        assert_eq!(lost, "/test/path");
157    }
158
159    // Test to_str
160    #[test]
161    fn test_to_str() {
162        let path = Path::new("/test/path");
163        assert_eq!(path.to_str(), Some("/test/path"));
164    }
165
166    // Test to_str with invalid unicode - simplified
167    #[test]
168    fn test_to_str_unicode() {
169        // Test normal unicode path
170        let path = Path::new("/test/文件.txt");
171        assert_eq!(path.to_str(), Some("/test/文件.txt"));
172    }
173
174    // Test clone
175    #[test]
176    fn test_clone() {
177        let path = Path::new("/test/path");
178        let cloned = path.clone();
179        assert_eq!(path, cloned);
180    }
181
182    // Test clone is independent
183    #[test]
184    fn test_clone_independence() {
185        let mut path1 = Path::new("/test/path");
186        let path2 = path1.clone();
187        path1 = Path::new("/other/path");
188        assert_eq!(path2.to_str(), Some("/test/path"));
189        assert_eq!(path1.to_str(), Some("/other/path"));
190    }
191
192    // Test equality
193    #[test]
194    fn test_eq() {
195        let path1 = Path::new("/test/path");
196        let path2 = Path::new("/test/path");
197        let path3 = Path::new("/other/path");
198
199        assert_eq!(path1, path2);
200        assert_ne!(path1, path3);
201    }
202
203    // Test equality with different types
204    #[test]
205    fn test_eq_with_std_path() {
206        let path = Path::new("/test/path");
207        let std_path = StdPath::new("/test/path");
208        // Can't directly compare different types without explicit conversion
209        assert_eq!(path.as_path(), std_path);
210    }
211
212    // Test Debug
213    #[test]
214    fn test_debug() {
215        let path = Path::new("/test/path");
216        let debug_str = format!("{:?}", path);
217        assert!(debug_str.contains("Path"));
218        assert!(debug_str.contains("/test/path"));
219    }
220
221    // Test Hash
222    #[test]
223    fn test_hash() {
224        use std::{
225            collections::hash_map::DefaultHasher,
226            hash::{
227                Hash,
228                Hasher,
229            },
230        };
231
232        let path1 = Path::new("/test/path");
233        let path2 = Path::new("/test/path");
234        let path3 = Path::new("/other/path");
235
236        let mut hasher1 = DefaultHasher::new();
237        let mut hasher2 = DefaultHasher::new();
238        let mut hasher3 = DefaultHasher::new();
239
240        path1.hash(&mut hasher1);
241        path2.hash(&mut hasher2);
242        path3.hash(&mut hasher3);
243
244        assert_eq!(hasher1.finish(), hasher2.finish());
245        assert_ne!(hasher1.finish(), hasher3.finish());
246    }
247
248    // Test PartialEq with PathBuf
249    #[test]
250    fn test_partial_eq_pathbuf() {
251        let path = Path::new("/test/path");
252        let pathbuf = PathBuf::from("/test/path");
253
254        assert_eq!(path.as_path(), pathbuf.as_path());
255    }
256
257    // Test as_os_str
258    #[test]
259    fn test_as_os_str() {
260        let path = Path::new("/test/path");
261        let os_str = path.as_os_str();
262        assert_eq!(os_str, std::ffi::OsStr::new("/test/path"));
263    }
264
265    // Test that path has content (skip is_empty - it's unstable)
266    #[test]
267    fn test_path_has_content() {
268        let path = Path::new("/test/path");
269        // Just verify the path string is not empty
270        assert!(!path.to_str().unwrap().is_empty());
271    }
272}