1use core::{cmp::Ordering, fmt};
5use serde::Deserialize;
6use std::{ffi::OsStr, ops::Deref, path::PathBuf, sync::Arc};
7
8#[derive(Clone, Deserialize)]
9#[serde(transparent)]
10pub struct Path {
11 path: Arc<OsStr>,
12}
13
14impl Path {
15 pub fn pop(&mut self) -> bool {
16 if let Some(parent) = self.parent() {
17 *self = parent.into();
18 true
19 } else {
20 false
21 }
22 }
23
24 pub fn push<V: AsRef<std::path::Path>>(&mut self, component: V) {
25 *self = self.join(component);
26 }
27
28 pub fn join<V: AsRef<std::path::Path>>(&self, component: V) -> Self {
29 self.as_ref().join(component).into()
30 }
31}
32
33impl PartialEq for Path {
34 fn eq(&self, other: &Self) -> bool {
35 self.as_ref().eq(other.as_ref())
36 }
37}
38
39impl Eq for Path {}
40
41impl PartialOrd for Path {
42 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
43 Some(self.cmp(other))
44 }
45}
46
47impl Ord for Path {
48 fn cmp(&self, other: &Self) -> Ordering {
49 self.as_ref().cmp(other.as_ref())
50 }
51}
52
53impl core::hash::Hash for Path {
54 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
55 self.as_ref().hash(state)
56 }
57}
58
59impl fmt::Debug for Path {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 self.as_ref().fmt(f)
62 }
63}
64
65impl fmt::Display for Path {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 let path = self.as_ref();
68 let path = crate::env::current_dir()
69 .ok()
70 .and_then(|dir| path.strip_prefix(dir).ok())
71 .unwrap_or(path);
72 path.display().fmt(f)
73 }
74}
75
76impl Deref for Path {
77 type Target = std::path::Path;
78
79 fn deref(&self) -> &Self::Target {
80 std::path::Path::new(&self.path)
81 }
82}
83
84impl AsRef<std::path::Path> for Path {
85 fn as_ref(&self) -> &std::path::Path {
86 self
87 }
88}
89
90impl PartialEq<str> for Path {
91 fn eq(&self, other: &str) -> bool {
92 self.as_ref().eq(std::path::Path::new(other))
93 }
94}
95
96impl PartialEq<std::path::Path> for Path {
97 fn eq(&self, other: &std::path::Path) -> bool {
98 self.as_ref().eq(other)
99 }
100}
101
102impl From<String> for Path {
103 fn from(path: String) -> Self {
104 Self {
105 path: PathBuf::from(path).into_os_string().into(),
106 }
107 }
108}
109
110impl From<PathBuf> for Path {
111 fn from(path: PathBuf) -> Self {
112 Self {
113 path: path.into_os_string().into(),
114 }
115 }
116}
117
118impl From<&PathBuf> for Path {
119 fn from(path: &PathBuf) -> Self {
120 path.as_path().into()
121 }
122}
123
124impl From<&std::path::Path> for Path {
125 fn from(path: &std::path::Path) -> Self {
126 Self {
127 path: path.as_os_str().into(),
128 }
129 }
130}
131
132impl From<Path> for PathBuf {
133 fn from(value: Path) -> Self {
134 PathBuf::from(&value.path)
135 }
136}
137
138impl From<&Path> for Path {
139 fn from(path: &Path) -> Self {
140 Self {
141 path: path.as_os_str().into(),
142 }
143 }
144}
145
146impl From<&str> for Path {
147 fn from(path: &str) -> Self {
148 Self {
149 path: std::path::Path::new(path).as_os_str().into(),
150 }
151 }
152}