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 if let Some(s) = self.get(key) {
151 s
152 } else {
153 ""
154 }
155 }
156
157 pub fn iter(&self) -> PathIter<'_, T> {
159 PathIter {
160 idx: 0,
161 params: self,
162 }
163 }
164
165 pub fn load<'de, U: serde::Deserialize<'de>>(&'de self) -> Result<U, de::value::Error> {
167 de::Deserialize::deserialize(PathDeserializer::new(self))
168 }
169}
170
171#[derive(Debug)]
173pub struct PathIter<'a, T> {
174 idx: usize,
175 params: &'a Path<T>,
176}
177
178impl<'a, T: ResourcePath> Iterator for PathIter<'a, T> {
179 type Item = (&'a str, &'a str);
180
181 #[inline]
182 fn next(&mut self) -> Option<(&'a str, &'a str)> {
183 if self.idx < self.params.len() {
184 let idx = self.idx;
185 let res = match self.params.segments[idx].1 {
186 PathItem::Static(s) => s,
187 PathItem::Segment(ref s) => s.as_str(),
188 PathItem::IdxSegment(s, e) => {
189 &self.params.path.path()[(s as usize)..(e as usize)]
190 }
191 };
192 self.idx += 1;
193 return Some((self.params.segments[idx].0, res));
194 }
195 None
196 }
197}
198
199impl<'a, T: ResourcePath> Index<&'a str> for Path<T> {
200 type Output = str;
201
202 fn index(&self, name: &'a str) -> &str {
203 self.get(name)
204 .expect("Value for parameter is not available")
205 }
206}
207
208impl<T: ResourcePath> Index<usize> for Path<T> {
209 type Output = str;
210
211 fn index(&self, idx: usize) -> &str {
212 match self.segments[idx].1 {
213 PathItem::Static(s) => s,
214 PathItem::Segment(ref s) => s,
215 PathItem::IdxSegment(s, e) => &self.path.path()[(s as usize)..(e as usize)],
216 }
217 }
218}
219
220impl<T: ResourcePath> Resource<T> for Path<T> {
221 fn path(&self) -> &str {
222 self.path()
223 }
224
225 fn resource_path(&mut self) -> &mut Path<T> {
226 self
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233
234 #[test]
235 fn test_path() {
236 let mut p: Path<String> = Path::default();
237 assert_eq!(p.get_ref(), &String::new());
238 p.get_mut().push_str("test");
239 assert_eq!(p.get_ref().as_str(), "test");
240 let p2 = p.clone();
241 assert_eq!(p2.get_ref().as_str(), "test");
242
243 p.skip(2);
244 assert_eq!(p.get("tail").unwrap(), "st");
245 assert_eq!(p.get("unknown"), None);
246 assert_eq!(p.query("tail"), "st");
247 assert_eq!(p.query("unknown"), "");
248 assert_eq!(p.unprocessed(), "st");
249
250 p.reset();
251 assert_eq!(p.unprocessed(), "test");
252
253 p.segments.push(("k1", PathItem::IdxSegment(0, 2)));
254 assert_eq!(p.get("k1").unwrap(), "te");
255 }
256}