1use std::ops::Index;
2
3use serde::de;
4
5use crate::de::PathDeserializer;
6use crate::{Resource, ResourcePath};
7
8#[derive(Debug, Clone)]
9pub(super) enum PathItem {
10 Static(&'static str),
11 Segment(String),
12 IdxSegment(u16, u16),
13}
14
15#[derive(Debug)]
19pub struct Path<T> {
20 path: T,
21 pub(super) skip: u16,
22 pub(super) segments: Vec<(&'static str, PathItem)>,
23}
24
25impl<T: Default> Default for Path<T> {
26 fn default() -> Self {
27 Path {
28 path: T::default(),
29 skip: 0,
30 segments: Vec::new(),
31 }
32 }
33}
34
35impl<T: Clone> Clone for Path<T> {
36 fn clone(&self) -> Self {
37 Path {
38 path: self.path.clone(),
39 skip: self.skip,
40 segments: self.segments.clone(),
41 }
42 }
43}
44
45impl<T: ResourcePath> Path<T> {
46 pub fn new(path: T) -> Path<T> {
47 Path {
48 path,
49 skip: 0,
50 segments: Vec::new(),
51 }
52 }
53
54 #[inline]
55 pub fn get_ref(&self) -> &T {
57 &self.path
58 }
59
60 #[inline]
61 pub fn get_mut(&mut self) -> &mut T {
63 &mut self.path
64 }
65
66 #[inline]
67 pub fn path(&self) -> &str {
69 let skip = self.skip as usize;
70 let path = self.path.path();
71 if skip <= path.len() {
72 &path[skip..]
73 } else {
74 ""
75 }
76 }
77
78 #[inline]
79 pub fn set(&mut self, path: T) {
81 self.skip = 0;
82 self.path = path;
83 self.segments.clear();
84 }
85
86 #[inline]
87 pub fn reset(&mut self) {
89 self.skip = 0;
90 self.segments.clear();
91 }
92
93 #[inline]
94 pub fn skip(&mut self, n: u16) {
96 self.skip += n;
97 }
98
99 #[doc(hidden)]
104 pub fn add_static(&mut self, name: &'static str, value: &'static str) {
105 self.segments.push((name, PathItem::Static(value)));
106 }
107
108 #[inline]
109 pub fn is_empty(&self) -> bool {
111 self.segments.is_empty()
112 }
113
114 #[inline]
115 pub fn len(&self) -> usize {
117 self.segments.len()
118 }
119
120 pub fn get(&self, key: &str) -> Option<&str> {
122 for item in self.segments.iter() {
123 if key == item.0 {
124 return match item.1 {
125 PathItem::Static(s) => Some(s),
126 PathItem::Segment(ref s) => Some(s),
127 PathItem::IdxSegment(s, e) => {
128 Some(&self.path.path()[(s as usize)..(e as usize)])
129 }
130 };
131 }
132 }
133 if key == "tail" {
134 Some(&self.path.path()[(self.skip as usize)..])
135 } else {
136 None
137 }
138 }
139
140 pub fn unprocessed(&self) -> &str {
142 &self.path.path()[(self.skip as usize)..]
143 }
144
145 pub fn query(&self, key: &str) -> &str {
150 self.get(key).unwrap_or_default()
151 }
152
153 pub fn iter(&self) -> PathIter<'_, T> {
155 PathIter {
156 idx: 0,
157 params: self,
158 }
159 }
160
161 pub fn load<'de, U: serde::Deserialize<'de>>(&'de self) -> Result<U, de::value::Error> {
163 de::Deserialize::deserialize(PathDeserializer::new(self))
164 }
165}
166
167#[derive(Debug)]
169pub struct PathIter<'a, T> {
170 idx: usize,
171 params: &'a Path<T>,
172}
173
174impl<'a, T: ResourcePath> Iterator for PathIter<'a, T> {
175 type Item = (&'a str, &'a str);
176
177 #[inline]
178 fn next(&mut self) -> Option<(&'a str, &'a str)> {
179 if self.idx < self.params.len() {
180 let idx = self.idx;
181 let res = match self.params.segments[idx].1 {
182 PathItem::Static(s) => s,
183 PathItem::Segment(ref s) => s.as_str(),
184 PathItem::IdxSegment(s, e) => {
185 &self.params.path.path()[(s as usize)..(e as usize)]
186 }
187 };
188 self.idx += 1;
189 return Some((self.params.segments[idx].0, res));
190 }
191 None
192 }
193}
194
195impl<'a, T: ResourcePath> Index<&'a str> for Path<T> {
196 type Output = str;
197
198 fn index(&self, name: &'a str) -> &str {
199 self.get(name)
200 .expect("Value for parameter is not available")
201 }
202}
203
204impl<T: ResourcePath> Index<usize> for Path<T> {
205 type Output = str;
206
207 fn index(&self, idx: usize) -> &str {
208 match self.segments[idx].1 {
209 PathItem::Static(s) => s,
210 PathItem::Segment(ref s) => s,
211 PathItem::IdxSegment(s, e) => &self.path.path()[(s as usize)..(e as usize)],
212 }
213 }
214}
215
216impl<T: ResourcePath> Resource<T> for Path<T> {
217 fn path(&self) -> &str {
218 self.path()
219 }
220
221 fn resource_path(&mut self) -> &mut Path<T> {
222 self
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_path() {
232 let mut p: Path<String> = Path::default();
233 assert_eq!(p.get_ref(), &String::new());
234 p.get_mut().push_str("test");
235 assert_eq!(p.get_ref().as_str(), "test");
236 let p2 = p.clone();
237 assert_eq!(p2.get_ref().as_str(), "test");
238
239 p.skip(2);
240 assert_eq!(p.get("tail").unwrap(), "st");
241 assert_eq!(p.get("unknown"), None);
242 assert_eq!(p.query("tail"), "st");
243 assert_eq!(p.query("unknown"), "");
244 assert_eq!(p.unprocessed(), "st");
245
246 p.reset();
247 assert_eq!(p.unprocessed(), "test");
248
249 p.segments.push(("k1", PathItem::IdxSegment(0, 2)));
250 assert_eq!(p.get("k1").unwrap(), "te");
251 }
252}