1#![allow(clippy::needless_pass_by_value)]
2use std::collections::HashMap;
3use std::hash::{Hash, Hasher};
4
5use regex::{Regex, escape};
6
7use super::IntoPattern;
8
9#[derive(Clone, Debug)]
10pub(super) struct Segments {
11 pub(super) tp: Vec<Segment>,
12 pub(super) slesh: bool,
13}
14
15#[derive(Clone, Debug)]
19pub struct ResourceDef {
20 id: u16,
21 pub(super) tp: Vec<Segments>, name: String,
23 pattern: String,
24 elements: Vec<PathElement>,
25 pub(super) prefix: bool,
26}
27
28#[derive(Debug, Clone, PartialEq)]
29enum PathElement {
30 Str(String),
31 Var(String),
32}
33
34impl PathElement {
35 fn is_str(&self) -> bool {
36 matches!(self, PathElement::Str(_))
37 }
38
39 fn into_str(self) -> String {
40 if let PathElement::Str(s) = self {
41 s
42 } else {
43 panic!()
44 }
45 }
46
47 fn as_str(&self) -> &str {
48 match self {
49 PathElement::Str(s) | PathElement::Var(s) => s.as_str(),
50 }
51 }
52}
53
54#[derive(Clone, Debug)]
55pub(crate) enum Segment {
56 Static(String),
57 Dynamic {
58 pattern: Regex,
59 names: Vec<&'static str>,
60 tail: bool,
61 },
62}
63
64impl Eq for Segment {}
65
66impl PartialEq for Segment {
67 fn eq(&self, other: &Self) -> bool {
68 match self {
69 Segment::Static(p1) => match other {
70 Segment::Static(p2) => p1 == p2,
71 Segment::Dynamic { .. } => false,
72 },
73 Segment::Dynamic {
74 pattern: p1,
75 tail: t1,
76 ..
77 } => match other {
78 Segment::Static { .. } => false,
79 Segment::Dynamic {
80 pattern: p2,
81 tail: t2,
82 ..
83 } => p1.as_str() == p2.as_str() && t1 == t2,
84 },
85 }
86 }
87}
88
89impl ResourceDef {
90 pub fn new<T: IntoPattern>(path: T) -> Self {
98 let set = path.patterns();
99 let mut p = String::new();
100 let mut tp = Vec::new();
101 let mut elements = Vec::new();
102
103 for path in set {
104 p.clone_from(&path);
105 let (pelems, elems) = ResourceDef::parse(&path);
106 tp.push(pelems);
107 elements = elems;
108 }
109
110 ResourceDef {
111 tp,
112 elements,
113 id: 0,
114 name: String::new(),
115 pattern: p,
116 prefix: false,
117 }
118 }
119
120 pub fn prefix<T: IntoPattern>(path: T) -> Self {
126 ResourceDef::with_prefix(path)
127 }
128
129 pub fn root_prefix<T: IntoPattern>(path: T) -> Self {
134 let mut patterns = path.patterns();
135 for path in &mut patterns {
136 let p = insert_slash(path.as_str());
137 *path = p;
138 }
139
140 ResourceDef::with_prefix(patterns)
141 }
142
143 pub fn id(&self) -> u16 {
145 self.id
146 }
147
148 pub fn set_id(&mut self, id: u16) {
150 self.id = id;
151 }
152
153 fn with_prefix<T: IntoPattern>(path: T) -> Self {
155 let patterns = path.patterns();
156
157 let mut p = String::new();
158 let mut tp = Vec::new();
159 let mut elements = Vec::new();
160
161 for path in patterns {
162 p.clone_from(&path);
163 let (pelems, elems) = ResourceDef::parse(&path);
164 tp.push(pelems);
165 elements = elems;
166 }
167
168 ResourceDef {
169 tp,
170 elements,
171 id: 0,
172 name: String::new(),
173 pattern: p,
174 prefix: true,
175 }
176 }
177
178 pub fn name(&self) -> &str {
180 &self.name
181 }
182
183 pub fn name_mut(&mut self) -> &mut String {
185 &mut self.name
186 }
187
188 pub fn pattern(&self) -> &str {
190 &self.pattern
191 }
192
193 pub fn resource_path<U, I>(&self, path: &mut String, elements: &mut U) -> bool
195 where
196 U: Iterator<Item = I>,
197 I: AsRef<str>,
198 {
199 for el in &self.elements {
200 match *el {
201 PathElement::Str(ref s) => path.push_str(s),
202 PathElement::Var(_) => {
203 if let Some(val) = elements.next() {
204 path.push_str(val.as_ref());
205 } else {
206 return false;
207 }
208 }
209 }
210 }
211 true
212 }
213
214 pub fn resource_path_named<K, V, S>(
216 &self,
217 path: &mut String,
218 elements: &HashMap<K, V, S>,
219 ) -> bool
220 where
221 K: std::borrow::Borrow<str> + Eq + Hash,
222 V: AsRef<str>,
223 S: std::hash::BuildHasher,
224 {
225 for el in &self.elements {
226 match *el {
227 PathElement::Str(ref s) => path.push_str(s),
228 PathElement::Var(ref name) => {
229 if let Some(val) = elements.get(name) {
230 path.push_str(val.as_ref());
231 } else {
232 return false;
233 }
234 }
235 }
236 }
237 true
238 }
239
240 fn parse_segment<'a>(
241 pattern: &'a str,
242 elems: &mut Vec<PathElement>,
243 ) -> (String, &'a str, bool) {
244 const DEFAULT_PATTERN: &str = ".+";
245 const DEFAULT_PATTERN_TAIL: &str = ".*";
246
247 let mut re = "^".to_string();
248 let mut end = None;
249 let mut tail = false;
250 let mut rem = pattern;
251 let start = usize::from(pattern.starts_with('/'));
252 let mut pattern = &pattern[start..];
253 elems.push(PathElement::Str('/'.to_string()));
254
255 while let Some(start_idx) = pattern.find('{') {
256 if let Some(end) = end
257 && start_idx > end
258 {
259 break;
260 }
261 let p = pattern.split_at(start_idx);
262 pattern = p.1;
263 re.push_str(&escape(p.0));
264 elems.push(PathElement::Str(p.0.to_string()));
265
266 let mut params_nesting = 0usize;
268 let close_idx = pattern
269 .find(|c| match c {
270 '{' => {
271 params_nesting += 1;
272 false
273 }
274 '}' => {
275 params_nesting -= 1;
276 params_nesting == 0
277 }
278 _ => false,
279 })
280 .expect("malformed dynamic segment");
281
282 let p = pattern.split_at(close_idx + 1);
283 rem = p.1;
284 let param = &p.0[1..p.0.len() - 1]; tail = rem == "*"; let (name, pat) = match param.find(':') {
288 Some(idx) => {
289 assert!(!tail, "Custom regex is not supported for remainder match");
290 let (name, pattern) = param.split_at(idx);
291 (name, &pattern[1..])
292 }
293 None => (
294 param,
295 if tail {
296 rem = &rem[1..];
297 DEFAULT_PATTERN_TAIL
298 } else {
299 DEFAULT_PATTERN
300 },
301 ),
302 };
303
304 re = format!(r"{}(?P<{}>{})", re, escape(name), pat);
305
306 elems.push(PathElement::Var(name.to_string()));
307
308 if let Some(idx) = rem.find(['{', '/']) {
309 end = Some(idx);
310 pattern = rem;
311 } else {
312 re += rem;
313 rem = "";
314 break;
315 }
316 }
317
318 if let Some(idx) = rem.find('/') {
320 re.push_str(&escape(&rem[..idx]));
321 rem = &rem[idx..];
322 } else {
323 re.push_str(&escape(rem));
324 rem = "";
325 }
326 re.push('$');
327
328 (re, rem, tail)
329 }
330
331 fn parse(mut pattern: &str) -> (Segments, Vec<PathElement>) {
332 let mut elems = Vec::new();
333 let mut pelems = Vec::new();
334
335 if pattern.is_empty() {
336 return (
337 Segments {
338 tp: Vec::new(),
339 slesh: false,
340 },
341 Vec::new(),
342 );
343 }
344
345 loop {
346 let start = usize::from(pattern.starts_with('/'));
347 let idx = if let Some(idx) = pattern[start..].find(['{', '/']) {
348 idx + start
349 } else {
350 break;
351 };
352
353 if let Some(i) = pattern[start..=idx].find('/') {
355 elems.push(PathElement::Str(pattern[..i + start].to_string()));
356 pelems.push(Segment::Static(pattern[start..i + start].to_string()));
357 pattern = &pattern[i + start..];
358 continue;
359 }
360
361 let (re_part, rem, tail) = Self::parse_segment(pattern, &mut elems);
363 let re = Regex::new(&re_part).unwrap();
364 let names: Vec<_> = re
365 .capture_names()
366 .filter_map(|name| name.map(|name| Box::leak(Box::new(name.to_owned())).as_str()))
367 .collect();
368 pelems.push(Segment::Dynamic {
369 names,
370 tail,
371 pattern: re,
372 });
373
374 pattern = rem;
375 if pattern.is_empty() {
376 break;
377 }
378 }
379
380 let slesh = pattern.ends_with('/');
382 if slesh {
383 pattern = &pattern[..pattern.len() - 1];
384 }
385 elems.push(PathElement::Str(pattern.to_string()));
386 if pattern.starts_with('/') {
387 pattern = &pattern[1..];
388 }
389 if !pattern.is_empty() {
390 if let Some(stripped) = pattern.strip_suffix('*') {
392 let pattern = Regex::new(&format!("^{stripped}(.+)")).unwrap();
393 pelems.push(Segment::Dynamic {
394 pattern,
395 names: Vec::new(),
396 tail: true,
397 });
398 } else {
399 pelems.push(Segment::Static(pattern.to_string()));
400 }
401 }
402
403 if slesh {
405 elems.push(PathElement::Str("/".to_string()));
406 }
407
408 let mut idx = 0;
410 while idx + 1 < elems.len() {
411 if elems[idx + 1].is_str() && elems[idx + 1].as_str().is_empty() {
412 elems.remove(idx + 1);
413 continue;
414 }
415 if elems[idx].is_str() && elems[idx + 1].is_str() {
416 let s2 = elems.remove(idx + 1).into_str();
417 if let PathElement::Str(ref mut s1) = elems[idx] {
418 s1.push_str(&s2);
419 continue;
420 }
421 }
422 idx += 1;
423 }
424
425 (Segments { tp: pelems, slesh }, elems)
426 }
427}
428
429impl Eq for ResourceDef {}
430
431impl PartialEq for ResourceDef {
432 fn eq(&self, other: &ResourceDef) -> bool {
433 self.pattern == other.pattern
434 }
435}
436
437impl Hash for ResourceDef {
438 fn hash<H: Hasher>(&self, state: &mut H) {
439 self.pattern.hash(state);
440 }
441}
442
443impl<'a> From<&'a str> for ResourceDef {
444 fn from(path: &'a str) -> ResourceDef {
445 ResourceDef::new(path)
446 }
447}
448
449impl From<String> for ResourceDef {
450 fn from(path: String) -> ResourceDef {
451 ResourceDef::new(path)
452 }
453}
454
455pub(crate) fn insert_slash(path: &str) -> String {
456 let mut path = path.to_owned();
457 if !path.is_empty() && !path.starts_with('/') {
458 path.insert(0, '/');
459 }
460 path
461}
462
463#[cfg(test)]
464mod tests {
465 use super::*;
466 use crate::path::Path;
467 use crate::tree::Tree;
468
469 #[test]
470 fn test_parse_static() {
471 let re = ResourceDef::new("/");
472 let tree = Tree::new(&re, 1);
473 assert_eq!(tree.find(&mut Path::new("/")), Some(1));
474 assert_eq!(tree.find(&mut Path::new("/a")), None);
475
476 let re = ResourceDef::new("/name");
477 let tree = Tree::new(&re, 1);
478 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
479 assert_eq!(tree.find(&mut Path::new("/")), None);
480 assert_eq!(tree.find(&mut Path::new("/name1")), None);
481 assert_eq!(tree.find(&mut Path::new("/name/")), None);
482 assert_eq!(tree.find(&mut Path::new("/name~")), None);
483
484 let re = ResourceDef::new("/name/");
485 let tree = Tree::new(&re, 1);
486 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
487 assert_eq!(tree.find(&mut Path::new("/name")), None);
488 assert_eq!(tree.find(&mut Path::new("/name/gs")), None);
489
490 let re = ResourceDef::new("/user/profile");
491 let tree = Tree::new(&re, 1);
492 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
493 assert_eq!(tree.find(&mut Path::new("/user/profile/profile")), None);
494
495 let mut tree = Tree::new(&ResourceDef::new("/name"), 1);
496 tree.insert(&ResourceDef::new("/name/"), 2);
497 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
498 assert_eq!(tree.find(&mut Path::new("/name/")), Some(2));
499
500 let mut tree = Tree::new(&ResourceDef::new(""), 1);
501 tree.insert(&ResourceDef::new("/test/index.html"), 2);
502 assert_eq!(tree.find_checked(&mut Path::new(""), &|_, _| true), Some(1));
503 assert_eq!(
504 tree.find_checked(&mut Path::new("index.html"), &|_, _| true),
505 None
506 );
507 assert_eq!(
508 tree.find_checked(&mut Path::new("test/index.html"), &|_, _| true),
509 Some(2)
510 );
511 }
512
513 #[test]
514 fn test_parse_param() {
515 let tree = Tree::new(&ResourceDef::new("/{id}"), 1);
516 assert_eq!(tree.find(&mut Path::new("/profile")), Some(1));
517 assert_eq!(tree.find(&mut Path::new("/2345")), Some(1));
518 assert_eq!(tree.find(&mut Path::new("/2345/")), None);
519 assert_eq!(tree.find(&mut Path::new("/2345/sdg")), None);
520
521 let re = ResourceDef::new("/user/{id}");
522 let tree = Tree::new(&re, 1);
523 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
524 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
525 assert_eq!(tree.find(&mut Path::new("/user/2345/")), None);
526 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), None);
527
528 let mut resource = Path::new("/user/profile");
529 let tree = Tree::new(&re, 1);
530 assert_eq!(tree.find(&mut resource), Some(1));
531 assert_eq!(resource.get("id").unwrap(), "profile");
532
533 let mut resource = Path::new("/user/1245125");
534 assert_eq!(tree.find(&mut resource), Some(1));
535 assert_eq!(resource.get("id").unwrap(), "1245125");
536
537 let tree = Tree::new(&ResourceDef::new("/v{version}/resource/{id}"), 1);
538 assert_eq!(tree.find(&mut Path::new("/v1/resource/320120")), Some(1));
539 assert_eq!(tree.find(&mut Path::new("/v1/resource/320120/")), None,);
540 assert_eq!(tree.find(&mut Path::new("/v/resource/1")), None);
541 assert_eq!(tree.find(&mut Path::new("/resource")), None);
542
543 let mut resource = Path::new("/v151/resource/adahg32");
544 assert_eq!(tree.find(&mut resource), Some(1));
545 assert_eq!(resource.get("version").unwrap(), "151");
546 assert_eq!(resource.get("id").unwrap(), "adahg32");
547
548 let re = ResourceDef::new("/{id:[[:digit:]]{6}}");
549 let tree = Tree::new(&re, 1);
550 assert_eq!(tree.find(&mut Path::new("/012345")), Some(1));
551 assert_eq!(tree.find(&mut Path::new("/012345/")), None);
552 assert_eq!(tree.find(&mut Path::new("/012345/index")), None);
553 assert_eq!(tree.find(&mut Path::new("/012")), None);
554 assert_eq!(tree.find(&mut Path::new("/01234567")), None);
555 assert_eq!(tree.find(&mut Path::new("/XXXXXX")), None);
556
557 let mut resource = Path::new("/012345");
558 assert_eq!(tree.find(&mut resource), Some(1));
559 assert_eq!(resource.get("id").unwrap(), "012345");
560
561 let re = ResourceDef::new("/u/test/v{version}-no-{minor}xx/resource/{id}/{name}");
562 let tree = Tree::new(&re, 1);
563 let mut resource = Path::new("/u/test/v1-no-3xx/resource/320120/name");
564 assert_eq!(tree.find(&mut resource), Some(1));
565 assert_eq!(resource.get("version").unwrap(), "1");
566 assert_eq!(resource.get("minor").unwrap(), "3");
567 assert_eq!(resource.get("id").unwrap(), "320120");
568 assert_eq!(resource.get("name").unwrap(), "name");
569 }
570
571 #[test]
572 fn test_dynamic_set() {
573 let re = ResourceDef::new(vec![
574 "/user/{id}",
575 "/v{version}/resource/{id}",
576 "/{id:[[:digit:]]{6}}",
577 ]);
578 let tree = Tree::new(&re, 1);
579 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
580 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
581 assert_eq!(tree.find(&mut Path::new("/user/2345/")), None);
582 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), None);
583
584 let mut resource = Path::new("/user/profile");
585 assert_eq!(tree.find(&mut resource), Some(1));
586 assert_eq!(resource.get("id").unwrap(), "profile");
587
588 let mut resource = Path::new("/user/1245125");
589 assert_eq!(tree.find(&mut resource), Some(1));
590 assert_eq!(resource.get("id").unwrap(), "1245125");
591
592 assert_eq!(tree.find(&mut Path::new("/v1/resource/320120")), Some(1));
593 assert_eq!(tree.find(&mut Path::new("/v/resource/1")), None);
594 assert_eq!(tree.find(&mut Path::new("/resource")), None);
595
596 let mut resource = Path::new("/v151/resource/adahg32");
597 assert_eq!(tree.find(&mut resource), Some(1));
598 assert_eq!(resource.get("version").unwrap(), "151");
599 assert_eq!(resource.get("id").unwrap(), "adahg32");
600
601 assert_eq!(tree.find(&mut Path::new("/012345")), Some(1));
602 assert_eq!(tree.find(&mut Path::new("/012")), None);
603 assert_eq!(tree.find(&mut Path::new("/01234567")), None);
604 assert_eq!(tree.find(&mut Path::new("/XXXXXX")), None);
605
606 let mut resource = Path::new("/012345");
607 assert_eq!(tree.find(&mut resource), Some(1));
608 assert_eq!(resource.get("id").unwrap(), "012345");
609
610 let re = ResourceDef::new([
611 "/user/{id}",
612 "/v{version}/resource/{id}",
613 "/{id:[[:digit:]]{6}}",
614 ]);
615 let tree = Tree::new(&re, 1);
616 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
617 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
618 assert_eq!(tree.find(&mut Path::new("/user/2345/")), None);
619 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), None);
620
621 let re = ResourceDef::new([
622 "/user/{id}".to_string(),
623 "/v{version}/resource/{id}".to_string(),
624 "/{id:[[:digit:]]{6}}".to_string(),
625 ]);
626 let tree = Tree::new(&re, 1);
627 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
628 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
629 assert_eq!(tree.find(&mut Path::new("/user/2345/")), None);
630 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), None);
631 }
632
633 #[cfg(feature = "http")]
634 #[test]
635 fn test_parse_urlencoded() {
636 use http::Uri;
637
638 let tree = Tree::new(&ResourceDef::new("/user/{id}/test"), 1);
639 let uri = Uri::try_from("/user/2345/test").unwrap();
640 let mut resource = Path::new(uri);
641 assert_eq!(tree.find(&mut resource), Some(1));
642 assert_eq!(resource.get("id").unwrap(), "2345");
643
644 let uri = Uri::try_from("/user/qwe%25/test").unwrap();
645 let mut resource = Path::new(uri);
646 assert_eq!(tree.find(&mut resource), Some(1));
647 assert_eq!(resource.get("id").unwrap(), "qwe%");
648
649 let uri = Uri::try_from("/user/qwe%25rty/test").unwrap();
650 let mut resource = Path::new(uri);
651 assert_eq!(tree.find(&mut resource), Some(1));
652 assert_eq!(resource.get("id").unwrap(), "qwe%rty");
653
654 let uri = Uri::try_from("/user/foo-%2f-%252f-bar/test").unwrap();
655 let mut resource = Path::new(uri);
656 assert_eq!(tree.find(&mut resource), Some(1));
657 assert_eq!(resource.get("id").unwrap(), "foo-/-%2f-bar");
658
659 let uri =
660 Uri::try_from("/user/http%3A%2F%2Flocalhost%3A80%2Ffile%2F%2Fvar%2Flog%2Fsyslog/test")
661 .unwrap();
662 let mut resource = Path::new(uri);
663 assert_eq!(tree.find(&mut resource), Some(1));
664 assert_eq!(
665 resource.get("id").unwrap(),
666 "http://localhost:80/file//var/log/syslog"
667 );
668 }
669
670 #[cfg(feature = "http")]
671 #[test]
672 fn test_extract_path_decode() {
673 use http::Uri;
674
675 let tree = Tree::new(&ResourceDef::new("/{id}/"), 1);
676
677 macro_rules! test_single_value {
678 ($value:expr, $expected:expr) => {{
679 let uri = Uri::try_from($value).unwrap();
680 let mut resource = Path::new(uri);
681 assert_eq!(tree.find(&mut resource), Some(1));
682 assert_eq!(resource.get("id").unwrap(), $expected);
683 }};
684 }
685
686 test_single_value!("/%25/", "%");
687 test_single_value!("/%40%C2%A3%24%25%5E%26%2B%3D/", "@£$%^&+=");
688 test_single_value!("/%2B/", "+");
689 test_single_value!("/%252B/", "%2B");
690 test_single_value!("/%2F/", "/");
691 test_single_value!("/test%2Ftest/", "test/test");
692 test_single_value!("/%252F/", "%2F");
693 test_single_value!("/%m/", "%m");
694 test_single_value!("/%mm/", "%mm");
695 test_single_value!("/test%mm/", "test%mm");
696 test_single_value!(
697 "/http%3A%2F%2Flocalhost%3A80%2Ffoo/",
698 "http://localhost:80/foo"
699 );
700 test_single_value!("/%2Fvar%2Flog%2Fsyslog/", "/var/log/syslog");
701 test_single_value!(
702 "/http%3A%2F%2Flocalhost%3A80%2Ffile%2F%252Fvar%252Flog%252Fsyslog/",
703 "http://localhost:80/file/%2Fvar%2Flog%2Fsyslog"
704 );
705 }
706
707 #[test]
708 #[allow(clippy::mutable_key_type)]
709 fn test_def() {
710 let re = ResourceDef::new("/user/-{id}*");
711 assert_eq!(re, ResourceDef::from("/user/-{id}*"));
712 assert_eq!(re, ResourceDef::from("/user/-{id}*".to_string()));
713
714 let mut h = HashMap::new();
715 h.insert(re.clone(), 1);
716 assert!(h.contains_key(&re));
717
718 let seg = Segment::Static("s".to_string());
719 assert_eq!(seg, Segment::Static("s".to_string()));
720
721 let seg2 = Segment::Dynamic {
722 pattern: Regex::new("test").unwrap(),
723 names: Vec::new(),
724 tail: false,
725 };
726 assert_ne!(seg, seg2);
727 assert_eq!(seg2, seg2);
728 }
729
730 #[test]
731 fn test_parse_tail() {
732 let re = ResourceDef::new("/user/-{id}*");
733 let tree = Tree::new(&re, 1);
734
735 let mut resource = Path::new("/user/-profile");
736 assert_eq!(tree.find(&mut resource), Some(1));
737 assert_eq!(resource.get("id").unwrap(), "profile");
738
739 let mut resource = Path::new("/user/-2345");
740 assert_eq!(tree.find(&mut resource), Some(1));
741 assert_eq!(resource.get("id").unwrap(), "2345");
742
743 let mut resource = Path::new("/user/-2345/");
744 assert_eq!(tree.find(&mut resource), Some(1));
745 assert_eq!(resource.get("id").unwrap(), "2345/");
746
747 let mut resource = Path::new("/user/-2345/sdg");
748 assert_eq!(tree.find(&mut resource), Some(1));
749 assert_eq!(resource.get("id").unwrap(), "2345/sdg");
750 }
751
752 #[test]
753 #[allow(clippy::needless_borrows_for_generic_args)]
754 fn test_static_tail() {
755 let re = ResourceDef::new("/*".to_string());
756 let tree = Tree::new(&re, 1);
757 assert_eq!(
758 tree.find(&mut Path::new(ntex_bytes::ByteString::from_static("/"))),
759 None
760 );
761 assert_eq!(tree.find(&mut Path::new("/profile")), Some(1));
762 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
763 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
764 assert_eq!(tree.find(&mut Path::new("/2345/")), Some(1));
765 assert_eq!(tree.find(&mut Path::new("/user/2345/")), Some(1));
766 assert_eq!(tree.find(&mut Path::new("/2345/sdg")), Some(1));
767 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), Some(1));
768
769 #[allow(clippy::needless_borrow)]
770 let re = ResourceDef::new(&("/user*".to_string()));
771 let tree = Tree::new(&re, 1);
772 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
773 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
774 assert_eq!(tree.find(&mut Path::new("/user/2345/")), Some(1));
775 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), Some(1));
776
777 let re = ResourceDef::new("/v/user*");
778 let tree = Tree::new(&re, 1);
779 assert_eq!(tree.find(&mut Path::new("/v/user/profile")), Some(1));
780 assert_eq!(tree.find(&mut Path::new("/v/user/2345")), Some(1));
781 assert_eq!(tree.find(&mut Path::new("/v/user/2345/")), Some(1));
782 assert_eq!(tree.find(&mut Path::new("/v/user/2345/sdg")), Some(1));
783
784 let re = ResourceDef::new("/user/*");
785 let tree = Tree::new(&re, 1);
786 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
787 assert_eq!(tree.find(&mut Path::new("/user/2345")), Some(1));
788 assert_eq!(tree.find(&mut Path::new("/user/2345/")), Some(1));
789 assert_eq!(tree.find(&mut Path::new("/user/2345/sdg")), Some(1));
790 assert_eq!(tree.find(&mut Path::new("/user/")), None);
791 assert_eq!(tree.find(&mut Path::new("/user")), None);
792
793 let re = ResourceDef::new("/v/user/*");
794 let tree = Tree::new(&re, 1);
795 assert_eq!(tree.find(&mut Path::new("/v/user/profile")), Some(1));
796 assert_eq!(tree.find(&mut Path::new("/v/user/2345")), Some(1));
797 assert_eq!(tree.find(&mut Path::new("/v/user/2345/")), Some(1));
798 assert_eq!(tree.find(&mut Path::new("/v/user/2345/sdg")), Some(1));
799 assert_eq!(tree.find(&mut Path::new("/v/user/")), None);
800 assert_eq!(tree.find(&mut Path::new("/v/user")), None);
801 }
802
803 #[test]
804 fn test_resource_prefix() {
805 let tree = Tree::new(&ResourceDef::prefix("/"), 1);
806 assert_eq!(tree.find(&mut Path::new("/")), Some(1));
807 assert_eq!(tree.find(&mut Path::new("/a")), Some(1));
808 assert_eq!(tree.find(&mut Path::new("/a/test/test")), Some(1));
809
810 let tree = Tree::new(&ResourceDef::prefix("/name"), 1);
811 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
812 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
813 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
814 assert_eq!(tree.find(&mut Path::new("/name1")), None);
815 assert_eq!(tree.find(&mut Path::new("/name~")), None);
816
817 let mut resource = Path::new("/name/subpath1/subpath2/index.html");
818 assert_eq!(tree.find(&mut resource), Some(1));
819 assert_eq!(resource.path(), "/subpath1/subpath2/index.html");
820
821 let tree = Tree::new(&ResourceDef::prefix("/name/"), 1);
822 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
823 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
824 assert_eq!(tree.find(&mut Path::new("/name")), None);
825 assert_eq!(tree.find(&mut Path::new("/name1")), None);
826
827 let tree = Tree::new(&ResourceDef::prefix(vec!["/name/", "/name2/"]), 1);
828 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
829 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
830 assert_eq!(tree.find(&mut Path::new("/name2/")), Some(1));
831 assert_eq!(tree.find(&mut Path::new("/name2/test/test")), Some(1));
832 assert_eq!(tree.find(&mut Path::new("/name")), None);
833 assert_eq!(tree.find(&mut Path::new("/name1")), None);
834
835 let tree = Tree::new(&ResourceDef::root_prefix("name/"), 1);
836 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
837 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
838 assert_eq!(tree.find(&mut Path::new("/name")), None);
839 assert_eq!(tree.find(&mut Path::new("/name1")), None);
840
841 let tree = Tree::new(&ResourceDef::root_prefix(vec!["name/", "name2/"]), 1);
842 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
843 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
844 assert_eq!(tree.find(&mut Path::new("/name2/")), Some(1));
845 assert_eq!(tree.find(&mut Path::new("/name2/test/test")), Some(1));
846 assert_eq!(tree.find(&mut Path::new("/name")), None);
847 assert_eq!(tree.find(&mut Path::new("/name1")), None);
848
849 let mut resource = Path::new("/name/subpath1/subpath2/index.html");
850 assert_eq!(tree.find(&mut resource), Some(1));
851 assert_eq!(resource.path(), "/subpath1/subpath2/index.html");
852 }
853
854 #[test]
855 fn test_reousrce_prefix_dynamic() {
856 let tree = Tree::new(&ResourceDef::prefix("/{name}/"), 1);
857 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
858 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
859 assert_eq!(tree.find(&mut Path::new("/name")), None);
860 assert_eq!(tree.find(&mut Path::new("/name1")), None);
861 assert_eq!(tree.find(&mut Path::new("/name~")), None);
862
863 let mut resource = Path::new("/test2/");
864 assert_eq!(tree.find(&mut resource), Some(1));
865 assert_eq!(&resource["name"], "test2");
866 assert_eq!(&resource[0], "test2");
867
868 let mut resource = Path::new("/test2/subpath1/subpath2/index.html");
869 assert_eq!(tree.find(&mut resource), Some(1));
870 assert_eq!(&resource["name"], "test2");
871 assert_eq!(&resource[0], "test2");
872 assert_eq!(resource.path(), "/subpath1/subpath2/index.html");
873
874 let tree = Tree::new(&ResourceDef::prefix("/{name}"), 1);
875 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
876 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
877 assert_eq!(tree.find(&mut Path::new("/name/test/test")), Some(1));
878 assert_eq!(tree.find(&mut Path::new("/name1")), Some(1));
879 assert_eq!(tree.find(&mut Path::new("/name~")), Some(1));
880
881 let tree = Tree::new(&ResourceDef::prefix(vec!["/1/{name}/", "/2/{name}/"]), 1);
882 assert_eq!(tree.find(&mut Path::new("/1/name/")), Some(1));
883 assert_eq!(tree.find(&mut Path::new("/1/name/test/test")), Some(1));
884 assert_eq!(tree.find(&mut Path::new("/2/name/")), Some(1));
885 assert_eq!(tree.find(&mut Path::new("/2/name/test/test")), Some(1));
886 assert_eq!(tree.find(&mut Path::new("/1/name")), None);
887 assert_eq!(tree.find(&mut Path::new("/1/name1")), None);
888 assert_eq!(tree.find(&mut Path::new("/1/name~")), None);
889 assert_eq!(tree.find(&mut Path::new("/2/name")), None);
890 assert_eq!(tree.find(&mut Path::new("/2/name1")), None);
891 assert_eq!(tree.find(&mut Path::new("/2/name~")), None);
892
893 let mut resource = Path::new("/1/test2/subpath1/subpath2/index.html");
894 assert_eq!(tree.find(&mut resource), Some(1));
895 assert_eq!(&resource["name"], "test2");
896 assert_eq!(&resource[0], "test2");
897 assert_eq!(resource.path(), "/subpath1/subpath2/index.html");
898
899 let mut resource = Path::new("/2/test3/subpath1/subpath2/index.html");
900 assert_eq!(tree.find(&mut resource), Some(1));
901 assert_eq!(&resource["name"], "test3");
902 assert_eq!(&resource[0], "test3");
903 assert_eq!(resource.path(), "/subpath1/subpath2/index.html");
904
905 let mut tree = Tree::new(&ResourceDef::prefix("/prefix/{v1}/second/{v2}"), 1);
907 tree.insert(&ResourceDef::prefix("/prefix/{v1}"), 2);
908
909 let mut resource = Path::new("/prefix/1/second/2");
910 assert_eq!(tree.find(&mut resource), Some(1));
911 assert_eq!(&resource["v1"], "1");
912 assert_eq!(&resource["v2"], "2");
913
914 let mut resource = Path::new("/prefix/1/second");
915 assert_eq!(tree.find(&mut resource), Some(2));
916 assert_eq!(&resource["v1"], "1");
917 assert_eq!(tree.find(&mut Path::new("/prefix/1")), Some(2));
918
919 let mut tree = Tree::new(
921 &ResourceDef::prefix(vec![
922 "/prefix/{v1}/second/{v2}",
923 "/prefix2/{v1}/second/{v2}",
924 ]),
925 1,
926 );
927 tree.insert(&ResourceDef::prefix("/prefix/{v1}"), 2);
928 tree.insert(&ResourceDef::prefix("/prefix2/{v1}"), 3);
929
930 let mut resource = Path::new("/prefix/1/second/2");
931 assert_eq!(tree.find(&mut resource), Some(1));
932 assert_eq!(&resource["v1"], "1");
933 assert_eq!(&resource["v2"], "2");
934
935 let mut resource = Path::new("/prefix2/1/second/2");
936 assert_eq!(tree.find(&mut resource), Some(1));
937 assert_eq!(&resource["v1"], "1");
938 assert_eq!(&resource["v2"], "2");
939
940 let mut resource = Path::new("/prefix/1/second");
941 assert_eq!(tree.find(&mut resource), Some(2));
942 assert_eq!(&resource["v1"], "1");
943 assert_eq!(tree.find(&mut Path::new("/prefix/1")), Some(2));
944
945 let mut resource = Path::new("/prefix2/1/second");
946 assert_eq!(tree.find(&mut resource), Some(3));
947 assert_eq!(&resource["v1"], "1");
948 assert_eq!(tree.find(&mut Path::new("/prefix2/1")), Some(3));
949 }
950
951 #[test]
952 fn test_resource_path() {
953 let mut s = String::new();
954 let resource = ResourceDef::new("/user/{item1}/test");
955 assert!(resource.resource_path(&mut s, &mut ["user1"].iter()));
956 assert_eq!(s, "/user/user1/test");
957
958 let mut s = String::new();
959 let resource = ResourceDef::new("/user/{item1}/{item2}/test");
960 assert!(resource.resource_path(&mut s, &mut ["item", "item2"].iter()));
961 assert_eq!(s, "/user/item/item2/test");
962
963 let mut s = String::new();
964 let resource = ResourceDef::new("/user/{item1}/{item2}");
965 assert!(resource.resource_path(&mut s, &mut ["item", "item2"].iter()));
966 assert_eq!(s, "/user/item/item2");
967
968 let mut s = String::new();
969 let resource = ResourceDef::new("/user/{item1}/{item2}/");
970 assert!(resource.resource_path(&mut s, &mut ["item", "item2"].iter()));
971 assert_eq!(s, "/user/item/item2/");
972
973 let mut s = String::new();
974 assert!(!resource.resource_path(&mut s, &mut ["item"].iter()));
975
976 let mut s = String::new();
977 assert!(resource.resource_path(&mut s, &mut ["item", "item2"].iter()));
978 assert_eq!(s, "/user/item/item2/");
979 assert!(!resource.resource_path(&mut s, &mut ["item"].iter()));
980
981 let mut s = String::new();
982 assert!(resource.resource_path(&mut s, &mut vec!["item", "item2"].into_iter()));
983 assert_eq!(s, "/user/item/item2/");
984
985 let mut map = HashMap::new();
986 map.insert("item1", "item");
987
988 let mut s = String::new();
989 assert!(!resource.resource_path_named(&mut s, &map));
990
991 let mut s = String::new();
992 map.insert("item2", "item2");
993 assert!(resource.resource_path_named(&mut s, &map));
994 assert_eq!(s, "/user/item/item2/");
995 }
996
997 #[test]
998 fn test_non_rooted() {
999 let tree = Tree::new(&ResourceDef::new("name"), 1);
1000 assert_eq!(tree.find(&mut Path::new("name")), Some(1));
1001 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
1002 assert_eq!(tree.find(&mut Path::new("/")), None);
1003 assert_eq!(tree.find(&mut Path::new("/name1")), None);
1004 assert_eq!(tree.find(&mut Path::new("/name/")), None);
1005 assert_eq!(tree.find(&mut Path::new("/name~")), None);
1006
1007 let tree = Tree::new(&ResourceDef::new("name/"), 1);
1008 assert_eq!(tree.find(&mut Path::new("name/")), Some(1));
1009 assert_eq!(tree.find(&mut Path::new("/name/")), Some(1));
1010 assert_eq!(tree.find(&mut Path::new("/name")), None);
1011 assert_eq!(tree.find(&mut Path::new("/name/gs")), None);
1012
1013 let tree = Tree::new(&ResourceDef::new("user/profile"), 1);
1014 assert_eq!(tree.find(&mut Path::new("user/profile")), Some(1));
1015 assert_eq!(tree.find(&mut Path::new("/user/profile")), Some(1));
1016 assert_eq!(tree.find(&mut Path::new("/user/profile/profile")), None);
1017
1018 let tree = Tree::new(&ResourceDef::new("{id}"), 1);
1019 assert_eq!(tree.find(&mut Path::new("profile")), Some(1));
1020 assert_eq!(tree.find(&mut Path::new("2345")), Some(1));
1021 assert_eq!(tree.find(&mut Path::new("/2345/")), None);
1022 assert_eq!(tree.find(&mut Path::new("/2345/sdg")), None);
1023
1024 let tree = Tree::new(&ResourceDef::new("{user}/profile/{no}"), 1);
1025 assert_eq!(tree.find(&mut Path::new("user/profile/123")), Some(1));
1026 assert_eq!(tree.find(&mut Path::new("/user/profile/123")), Some(1));
1027 assert_eq!(tree.find(&mut Path::new("/user/profile/p/test/")), None);
1028
1029 let tree = Tree::new(&ResourceDef::new("v{version}/resource/{id}/test"), 1);
1030 assert_eq!(
1031 tree.find(&mut Path::new("v1/resource/320120/test")),
1032 Some(1)
1033 );
1034 assert_eq!(tree.find(&mut Path::new("v/resource/1/test")), None);
1035
1036 let mut resource = Path::new("v151/resource/adahg32/test");
1037 assert_eq!(tree.find(&mut resource), Some(1));
1038 assert_eq!(resource.get("version").unwrap(), "151");
1039 assert_eq!(resource.get("id").unwrap(), "adahg32");
1040
1041 let re = ResourceDef::new("v/{id:[[:digit:]]{6}}");
1042 let tree = Tree::new(&re, 1);
1043 assert_eq!(tree.find(&mut Path::new("v/012345")), Some(1));
1044 assert_eq!(tree.find(&mut Path::new("v/012345/")), None);
1045 assert_eq!(tree.find(&mut Path::new("v/012345/index")), None);
1046 assert_eq!(tree.find(&mut Path::new("v/012")), None);
1047 assert_eq!(tree.find(&mut Path::new("v/01234567")), None);
1048 assert_eq!(tree.find(&mut Path::new("v/XXXXXX")), None);
1049
1050 let mut resource = Path::new("v/012345");
1051 assert_eq!(tree.find(&mut resource), Some(1));
1052 assert_eq!(resource.get("id").unwrap(), "012345");
1053
1054 let re = ResourceDef::new("u/test/v{version}-no-{minor}xx/resource/{id}/{name}");
1055 let tree = Tree::new(&re, 1);
1056 let mut resource = Path::new("u/test/v1-no-3xx/resource/320120/name");
1057 assert_eq!(tree.find(&mut resource), Some(1));
1058 assert_eq!(resource.get("version").unwrap(), "1");
1059 assert_eq!(resource.get("minor").unwrap(), "3");
1060 assert_eq!(resource.get("id").unwrap(), "320120");
1061 assert_eq!(resource.get("name").unwrap(), "name");
1062 }
1063
1064 #[test]
1065 fn test_recursive() {
1066 let mut tree = Tree::new(&ResourceDef::new("/name"), 1);
1067 tree.insert(&ResourceDef::new("/name/"), 2);
1068 tree.insert(&ResourceDef::new("/name/index.html"), 3);
1069 tree.insert(&ResourceDef::prefix("/"), 4);
1070
1071 assert_eq!(tree.find(&mut Path::new("/name")), Some(1));
1072 assert_eq!(tree.find(&mut Path::new("/name/")), Some(2));
1073 assert_eq!(tree.find(&mut Path::new("/name/index.html")), Some(3));
1074 assert_eq!(tree.find(&mut Path::new("/")), Some(4));
1075 assert_eq!(tree.find(&mut Path::new("/test")), Some(4));
1076 assert_eq!(tree.find(&mut Path::new("/test/index.html")), Some(4));
1077 }
1078
1079 #[test]
1080 fn test_with_some_match() {
1081 let mut tree = Tree::new(&ResourceDef::new("/p/{tp}/{id}/{r}"), 1);
1082 tree.insert(&ResourceDef::new("/p/ih/{tp}/d/{id}/sid/{r}/r/{s}"), 3);
1083
1084 let mut p = Path::new("/p/ih/def/d/abc/sid/5bddc58f/r/srv");
1085 assert_eq!(tree.find(&mut p), Some(3));
1086 assert_eq!(p.get("tp"), Some("def"));
1087 assert_eq!(p.get("id"), Some("abc"));
1088 assert_eq!(p.get("r"), Some("5bddc58f"));
1089 assert_eq!(p.get("s"), Some("srv"));
1090 assert_eq!(p.len(), 4);
1091 }
1092}