lutra_compiler/pr/
path.rs1#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
4pub struct Path {
5 path: Vec<String>,
6}
7
8impl Path {
9 pub fn new<S: ToString, I: IntoIterator<Item = S>>(path: I) -> Self {
11 Path {
12 path: path.into_iter().map(|x| x.to_string()).collect(),
13 }
14 }
15 pub fn empty() -> Self {
16 Path { path: vec![] }
17 }
18
19 pub fn from_name<S: ToString>(name: S) -> Self {
20 Path {
21 path: vec![name.to_string()],
22 }
23 }
24
25 pub fn first(&self) -> &str {
26 self.path.first().unwrap()
27 }
28
29 pub fn last(&self) -> &str {
30 self.path.last().unwrap()
31 }
32
33 pub fn parent(&self) -> Option<&[String]> {
34 if self.is_empty() {
35 None
36 } else {
37 Some(&self.path[0..(self.len() - 1)])
38 }
39 }
40
41 pub fn as_steps(&self) -> &[String] {
42 &self.path
43 }
44
45 pub fn len(&self) -> usize {
46 self.path.len()
47 }
48
49 pub fn is_empty(&self) -> bool {
50 self.path.is_empty()
51 }
52
53 pub fn prepend(&mut self, mut prefix: Path) {
54 prefix.path.append(&mut self.path);
55 self.path = prefix.path;
56 }
57
58 pub fn append(mut self, suffix: Path) -> Path {
59 self.path.extend(suffix.path);
60 self
61 }
62
63 pub fn extend(&mut self, suffix: Path) {
64 self.path.extend(suffix);
65 }
66
67 pub fn push(&mut self, name: String) {
68 self.path.push(name);
69 }
70
71 pub fn pop(&mut self) -> Option<String> {
72 self.path.pop()
73 }
74
75 pub fn pop_first(&mut self) -> Option<String> {
76 if self.is_empty() {
77 return None;
78 }
79 let remaining = self.path.split_off(1);
80 let first = std::mem::replace(&mut self.path, remaining);
81 Some(first.into_iter().next().unwrap())
82 }
83
84 pub fn with_name<S: ToString>(mut self, name: S) -> Self {
85 *self.path.last_mut().unwrap() = name.to_string();
86 self
87 }
88
89 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &String> {
90 self.path.iter()
91 }
92
93 pub fn starts_with(&self, prefix: &Path) -> bool {
94 if prefix.len() > self.len() {
95 return false;
96 }
97 prefix
98 .iter()
99 .zip(self.iter())
100 .all(|(prefix_component, self_component)| prefix_component == self_component)
101 }
102
103 pub fn starts_with_path<S: AsRef<str>>(&self, prefix: &[S]) -> bool {
104 if prefix.len() > self.len() {
106 return false;
107 }
108 prefix
109 .iter()
110 .zip(self.iter())
111 .all(|(prefix_component, self_component)| prefix_component.as_ref() == self_component)
112 }
113
114 pub fn starts_with_part(&self, prefix: &str) -> bool {
115 self.starts_with_path(&[prefix])
116 }
117}
118
119impl std::fmt::Debug for Path {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 f.write_str(&display_path(self))
122 }
123}
124
125impl std::fmt::Display for Path {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 f.write_str(&display_path(self))
128 }
129}
130
131impl IntoIterator for Path {
132 type Item = String;
133 type IntoIter = std::vec::IntoIter<std::string::String>;
134
135 fn into_iter(self) -> Self::IntoIter {
136 self.path.into_iter()
137 }
138}
139
140impl std::ops::Add<Path> for Path {
141 type Output = Path;
142
143 fn add(mut self, rhs: Path) -> Self::Output {
144 self.path.extend(rhs.path);
145 self
146 }
147}
148
149fn display_path(ident: &Path) -> String {
150 let path = &ident.path[..];
151
152 let mut r = String::new();
153 for (index, part) in path.iter().enumerate() {
154 if index > 0 {
155 r += "::";
156 }
157 r += lutra_bin::ident::display(part).as_ref();
158 }
159 r
160}