1pub mod path_segment;
4
5use crate::Identifier;
6use crate::prelude::*;
7use std::path::PathBuf;
8
9pub use path_segment::PathSegment;
10
11#[cfg(any(test, feature = "mocks"))]
12pub mod mock;
13
14#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
16pub struct Path {
17 pub segments: Vec<PathSegment>
19}
20
21impl From<is_tree::Path> for Path {
22 fn from(path: is_tree::Path) -> Self {
23 let segments = path
24 .segments
25 .iter()
26 .map(|segment| segment.clone().into())
27 .collect();
28 Self { segments }
29 }
30}
31
32impl Path {
33 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn is_empty(&self) -> bool {
40 self.segments.is_empty()
41 }
42
43 pub fn from_string_with_separator(string: &str, separator: impl AsRef<str>) -> Self {
45 let separator = separator.as_ref();
46 let segments = string
47 .split(separator)
48 .map(PathSegment::from)
49 .collect();
50 Self { segments }
51
52 }
53
54 pub fn to_string_with_separator(&self, separator: impl AsRef<str>) -> String {
56 let separator = separator.as_ref();
57 let segments: Vec<_> = self.segments.iter().map(|identifier| identifier.to_string()).collect();
58 segments.join(separator)
59 }
60
61 pub fn first(&self) -> &PathSegment {
63 self.segments.first().unwrap()
64 }
65
66 pub fn first_mut(&mut self) -> &mut PathSegment {
68 self.segments.first_mut().unwrap()
69 }
70
71 pub fn last(&self) -> &PathSegment {
73 self.segments.last().unwrap()
74 }
75
76 pub fn last_mut(&mut self) -> &mut PathSegment {
78 self.segments.last_mut().unwrap()
79 }
80
81 pub fn join<T: Into<Path>>(self, another: T) -> Self {
83 let mut this = self;
84 this.segments.append(&mut another.into().segments);
85 this
86 }
87
88 pub fn without_first(mut self) -> Self {
90 self.pop_front();
91 self
92 }
93
94 pub fn without_last(mut self) -> Self {
96 self.pop_back();
97 self
98 }
99
100 pub fn pop_front(&mut self) -> Option<PathSegment> {
102 if !self.segments.is_empty() {
103 Some(self.segments.remove(0))
104 } else {
105 None
106 }
107 }
108
109 pub fn pop_back(&mut self) -> Option<PathSegment> {
111 self.segments.pop()
112 }
113
114 pub fn push_front(&mut self, segment: impl Into<PathSegment>) {
116 self.segments.insert(0, segment.into());
117 }
118
119 pub fn push_back(&mut self, segment: impl Into<PathSegment>) {
121 self.segments.push(segment.into());
122 }
123}
124
125impl<I: Into<Identifier>> From<Vec<I>> for Path {
126 fn from(from: Vec<I>) -> Self {
127 let segments = from
128 .into_iter()
129 .map(|x| x.into().into())
130 .collect();
131 Self { segments }
132 }
133}
134
135impl From<PathSegment> for Path {
136 fn from(segment: PathSegment) -> Self {
137 Self { segments: vec![segment] }
138 }
139}
140
141impl From<&[&str]> for Path {
142 fn from(from: &[&str]) -> Self {
143 let segments = from
144 .iter()
145 .map(|x| (*x).into())
146 .collect();
147 Self { segments }
148 }
149
150}
151
152impl From<&str> for Path {
153 fn from(string: &str) -> Path {
154 Self::from_string_with_separator(string, "::")
155 }
156}
157
158impl From<String> for Path {
159 fn from(string: String) -> Path {
160 string.as_str().into()
161 }
162}
163
164impl From<PathBuf> for Path {
165 fn from(path: PathBuf) -> Self {
166 let segments = path
167 .iter()
168 .filter_map(|segment| segment.to_str())
169 .map(|segment| segment.into())
170 .collect();
171 Self { segments }
172 }
173}
174
175impl From<Path> for PathBuf {
176 fn from(path: Path) -> Self {
177 let mut path_buf = PathBuf::new();
178 for segment in path.segments {
179 path_buf = path_buf.join(segment.identifier.name);
180 }
181 path_buf
182 }
183}
184
185impl From<Identifier> for Path {
186 fn from(identifier: Identifier) -> Self {
187 let segments = vec![identifier.into()];
188 Self { segments }
189 }
190}
191
192impl std::fmt::Display for Path {
193 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
194 f.write_str(self.to_string_with_separator("::").as_str())
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use super::*;
201 #[test]
202 fn path_from_string() {
203 let path: Path = "std::convert::TryFrom".into();
204 let segments: Vec<_> = vec!["std", "convert", "TryFrom"]
205 .into_iter()
206 .map(PathSegment::from)
207 .collect();
208 assert_eq!(path.segments, segments);
209 }
210}