1use std::ops::Index;
2
3use serde::de;
4
5use crate::de::PathDeserializer;
6use crate::{Resource, ResourcePath};
7
8#[derive(Debug, Clone, Copy)]
9pub(crate) enum PathItem {
10 Static(&'static str),
11 Segment(u16, u16),
12}
13
14#[derive(Debug)]
18pub struct Path<T> {
19 path: T,
20 pub(crate) skip: u16,
21 pub(crate) segments: Vec<(&'static str, PathItem)>,
22}
23
24impl<T: Default> Default for Path<T> {
25 fn default() -> Self {
26 Path {
27 path: T::default(),
28 skip: 0,
29 segments: Vec::new(),
30 }
31 }
32}
33
34impl<T: Clone> Clone for Path<T> {
35 fn clone(&self) -> Self {
36 Path {
37 path: self.path.clone(),
38 skip: self.skip,
39 segments: self.segments.clone(),
40 }
41 }
42}
43
44impl<T: ResourcePath> Path<T> {
45 pub fn new(path: T) -> Path<T> {
46 Path {
47 path,
48 skip: 0,
49 segments: Vec::new(),
50 }
51 }
52
53 #[inline]
54 pub fn get_ref(&self) -> &T {
56 &self.path
57 }
58
59 #[inline]
60 pub fn get_mut(&mut self) -> &mut T {
62 &mut self.path
63 }
64
65 #[inline]
66 pub fn path(&self) -> &str {
68 let skip = self.skip as usize;
69 let path = self.path.path();
70 if skip <= path.len() {
71 &path[skip..]
72 } else {
73 ""
74 }
75 }
76
77 #[inline]
78 pub fn set(&mut self, path: T) {
80 self.skip = 0;
81 self.path = path;
82 self.segments.clear();
83 }
84
85 #[inline]
86 pub fn reset(&mut self) {
88 self.skip = 0;
89 self.segments.clear();
90 }
91
92 #[inline]
93 pub fn skip(&mut self, n: u16) {
95 self.skip += n;
96 }
97
98 pub(crate) fn add(&mut self, name: &'static str, value: PathItem) {
99 match value {
100 PathItem::Static(s) => self.segments.push((name, PathItem::Static(s))),
101 PathItem::Segment(begin, end) => self
102 .segments
103 .push((name, PathItem::Segment(self.skip + begin, self.skip + end))),
104 }
105 }
106
107 #[doc(hidden)]
108 pub fn add_static(&mut self, name: &'static str, value: &'static str) {
109 self.segments.push((name, PathItem::Static(value)));
110 }
111
112 #[inline]
113 pub fn is_empty(&self) -> bool {
115 self.segments.is_empty()
116 }
117
118 #[inline]
119 pub fn len(&self) -> usize {
121 self.segments.len()
122 }
123
124 pub fn get(&self, key: &str) -> Option<&str> {
126 for item in self.segments.iter() {
127 if key == item.0 {
128 return match item.1 {
129 PathItem::Static(ref s) => Some(&s),
130 PathItem::Segment(s, e) => {
131 Some(&self.path.path()[(s as usize)..(e as usize)])
132 }
133 };
134 }
135 }
136 if key == "tail" {
137 Some(&self.path.path()[(self.skip as usize)..])
138 } else {
139 None
140 }
141 }
142
143 pub fn unprocessed(&self) -> &str {
145 &self.path.path()[(self.skip as usize)..]
146 }
147
148 pub fn query(&self, key: &str) -> &str {
153 if let Some(s) = self.get(key) {
154 s
155 } else {
156 ""
157 }
158 }
159
160 pub fn iter(&self) -> PathIter<T> {
162 PathIter {
163 idx: 0,
164 params: self,
165 }
166 }
167
168 pub fn load<'de, U: serde::Deserialize<'de>>(&'de self) -> Result<U, de::value::Error> {
170 de::Deserialize::deserialize(PathDeserializer::new(self))
171 }
172}
173
174#[derive(Debug)]
175pub struct PathIter<'a, T> {
176 idx: usize,
177 params: &'a Path<T>,
178}
179
180impl<'a, T: ResourcePath> Iterator for PathIter<'a, T> {
181 type Item = (&'a str, &'a str);
182
183 #[inline]
184 fn next(&mut self) -> Option<(&'a str, &'a str)> {
185 if self.idx < self.params.len() {
186 let idx = self.idx;
187 let res = match self.params.segments[idx].1 {
188 PathItem::Static(ref s) => &s,
189 PathItem::Segment(s, e) => &self.params.path.path()[(s as usize)..(e as usize)],
190 };
191 self.idx += 1;
192 return Some((&self.params.segments[idx].0, res));
193 }
194 None
195 }
196}
197
198impl<'a, T: ResourcePath> Index<&'a str> for Path<T> {
199 type Output = str;
200
201 fn index(&self, name: &'a str) -> &str {
202 self.get(name)
203 .expect("Value for parameter is not available")
204 }
205}
206
207impl<T: ResourcePath> Index<usize> for Path<T> {
208 type Output = str;
209
210 fn index(&self, idx: usize) -> &str {
211 match self.segments[idx].1 {
212 PathItem::Static(ref s) => &s,
213 PathItem::Segment(s, e) => &self.path.path()[(s as usize)..(e as usize)],
214 }
215 }
216}
217
218impl<T: ResourcePath> Resource<T> for Path<T> {
219 fn resource_path(&mut self) -> &mut Self {
220 self
221 }
222}