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}