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