uri_rs/ast/
path.rs

1use std::fmt;
2use std::fmt::Formatter;
3
4use itertools::Itertools;
5
6#[derive(Debug, Clone, PartialEq, Hash)]
7pub enum Path {
8  RootlessPath {
9    type_name: &'static str,
10    parts: Vec<String>,
11  },
12  AbemptyPath {
13    type_name: &'static str,
14    parts: Vec<String>,
15  },
16  AbsolutePath {
17    type_name: &'static str,
18    parts: Vec<String>,
19  },
20  NoSchemePath {
21    type_name: &'static str,
22    parts: Vec<String>,
23  },
24  EmptyPath {
25    type_name: &'static str,
26  },
27}
28
29impl Default for Path {
30  fn default() -> Self {
31    Path::of_empty()
32  }
33}
34
35impl fmt::Display for Path {
36  fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
37    let root = match self {
38      Path::RootlessPath { .. } | Path::NoSchemePath { .. } | Path::EmptyPath { .. } => "",
39      _ => "/",
40    };
41    write!(f, "{}{}", root, self.parts().join("/"))
42  }
43}
44
45impl Path {
46  pub fn of_rootless_from_strs(parts: &[&str]) -> Self {
47    Path::RootlessPath {
48      type_name: "rootless_path",
49      parts: parts.into_iter().map(|e| e.to_string()).collect_vec(),
50    }
51  }
52
53  pub fn of_rootless_from_strings(parts: &[String]) -> Self {
54    Path::RootlessPath {
55      type_name: "rootless_path",
56      parts: Vec::from(parts),
57    }
58  }
59
60  pub fn of_abempty_from_strs(parts: &[&str]) -> Self {
61    Path::AbemptyPath {
62      type_name: "abempty_path",
63      parts: parts.into_iter().map(|e| e.to_string()).collect_vec(),
64    }
65  }
66
67  pub fn of_abempty_from_strings(parts: &[String]) -> Self {
68    Path::AbemptyPath {
69      type_name: "abempty_path",
70      parts: Vec::from(parts),
71    }
72  }
73
74  pub fn of_absolute_from_strs(parts: &[&str]) -> Self {
75    Path::AbsolutePath {
76      type_name: "absolute_path",
77      parts: parts.into_iter().map(|e| e.to_string()).collect_vec(),
78    }
79  }
80
81  pub fn of_absolute_from_strings(parts: &[String]) -> Self {
82    Path::AbsolutePath {
83      type_name: "absolute_path",
84      parts: Vec::from(parts),
85    }
86  }
87
88  pub fn of_no_scheme_from_strs(parts: &[&str]) -> Self {
89    Path::NoSchemePath {
90      type_name: "no_scheme_path",
91      parts: parts.into_iter().map(|e| e.to_string()).collect_vec(),
92    }
93  }
94
95  pub fn of_no_scheme_from_strings(parts: &[String]) -> Self {
96    Path::NoSchemePath {
97      type_name: "no_scheme_path",
98      parts: Vec::from(parts),
99    }
100  }
101
102  pub fn of_empty() -> Self {
103    Path::EmptyPath {
104      type_name: "empty_path",
105    }
106  }
107
108  pub fn type_name(&self) -> &'static str {
109    match self {
110      &Path::RootlessPath { type_name, .. } => type_name,
111      &Path::AbemptyPath { type_name, .. } => type_name,
112      &Path::AbsolutePath { type_name, .. } => type_name,
113      &Path::NoSchemePath { type_name, .. } => type_name,
114      &Path::EmptyPath { type_name } => type_name,
115    }
116  }
117  pub fn parts(&self) -> &Vec<String> {
118    static EMPTY_PARTS: Vec<String> = vec![];
119    match self {
120      Path::RootlessPath { parts, .. } => parts,
121      Path::AbemptyPath { parts, .. } => parts,
122      Path::AbsolutePath { parts, .. } => parts,
123      Path::NoSchemePath { parts, .. } => parts,
124      Path::EmptyPath { .. } => &EMPTY_PARTS,
125    }
126  }
127
128  pub fn is_empty(&self) -> bool {
129    self.parts().is_empty()
130  }
131
132  pub fn non_empty(&self) -> bool {
133    !self.is_empty()
134  }
135
136  pub fn with_parts(&mut self, parts: Vec<String>) {
137    self.add_parts(parts)
138  }
139
140  pub fn to_rootless(&self) -> Path {
141    Path::of_rootless_from_strings(&self.parts().clone())
142  }
143
144  pub fn to_absolute(&self) -> Path {
145    Path::of_absolute_from_strings(&self.parts().clone())
146  }
147
148  pub fn add_part(&mut self, part: String) {
149    let parts_opt = match self {
150      Path::RootlessPath { parts, .. } => Some(parts),
151      Path::AbemptyPath { parts, .. } => Some(parts),
152      Path::AbsolutePath { parts, .. } => Some(parts),
153      Path::NoSchemePath { parts, .. } => Some(parts),
154      Path::EmptyPath { .. } => None,
155    };
156    match parts_opt {
157      Some(parts) => {
158        parts.push(part);
159      }
160      None => (),
161    }
162  }
163
164  pub fn add_parts(&mut self, parts: Vec<String>) {
165    for x in parts {
166      self.add_part(x)
167    }
168  }
169}