From a2a9d9764d9471f9df13a972ac3c232050d7067e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 25 Dec 2019 19:54:20 +0400 Subject: [PATCH] introduce IntoPattern trait --- router/CHANGES.txt | 4 ++-- router/src/de.rs | 2 +- router/src/lib.rs | 54 ++++++++++++++++++++++++++++++++++++++---- router/src/resource.rs | 40 ++++++++++++++++++------------- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/router/CHANGES.txt b/router/CHANGES.txt index 6e1bc8ae..d966586f 100644 --- a/router/CHANGES.txt +++ b/router/CHANGES.txt @@ -1,8 +1,8 @@ # Changes -## [0.2.1] - 2019-12-xx +## [0.2.1] - 2019-12-25 -* Add `IntoPatterns` trait +* Add `IntoPattern` trait * Add multi-pattern resources diff --git a/router/src/de.rs b/router/src/de.rs index 56dac4e7..3621309b 100644 --- a/router/src/de.rs +++ b/router/src/de.rs @@ -492,7 +492,7 @@ mod tests { #[derive(Deserialize)] struct Id { - id: String, + _id: String, } #[derive(Debug, Deserialize)] diff --git a/router/src/lib.rs b/router/src/lib.rs index e2a5a7fd..21984404 100644 --- a/router/src/lib.rs +++ b/router/src/lib.rs @@ -36,14 +36,14 @@ impl ResourcePath for bytestring::ByteString { } /// Helper trait for type that could be converted to path pattern -pub trait IntoPatterns { +pub trait IntoPattern { /// Signle patter fn is_single(&self) -> bool; fn patterns(&self) -> Vec; } -impl IntoPatterns for String { +impl IntoPattern for String { fn is_single(&self) -> bool { true } @@ -53,7 +53,7 @@ impl IntoPatterns for String { } } -impl<'a> IntoPatterns for &'a str { +impl<'a> IntoPattern for &'a str { fn is_single(&self) -> bool { true } @@ -63,7 +63,7 @@ impl<'a> IntoPatterns for &'a str { } } -impl> IntoPatterns for Vec { +impl> IntoPattern for Vec { fn is_single(&self) -> bool { self.len() == 1 } @@ -73,6 +73,52 @@ impl> IntoPatterns for Vec { } } +macro_rules! array_patterns (($tp:ty, $num:tt) => { + impl IntoPattern for [$tp; $num] { + fn is_single(&self) -> bool { + $num == 1 + } + + fn patterns(&self) -> Vec { + self.iter().map(|v| v.to_string()).collect() + } + } +}); + +array_patterns!(&str, 1); +array_patterns!(&str, 2); +array_patterns!(&str, 3); +array_patterns!(&str, 4); +array_patterns!(&str, 5); +array_patterns!(&str, 6); +array_patterns!(&str, 7); +array_patterns!(&str, 8); +array_patterns!(&str, 9); +array_patterns!(&str, 10); +array_patterns!(&str, 11); +array_patterns!(&str, 12); +array_patterns!(&str, 13); +array_patterns!(&str, 14); +array_patterns!(&str, 15); +array_patterns!(&str, 16); + +array_patterns!(String, 1); +array_patterns!(String, 2); +array_patterns!(String, 3); +array_patterns!(String, 4); +array_patterns!(String, 5); +array_patterns!(String, 6); +array_patterns!(String, 7); +array_patterns!(String, 8); +array_patterns!(String, 9); +array_patterns!(String, 10); +array_patterns!(String, 11); +array_patterns!(String, 12); +array_patterns!(String, 13); +array_patterns!(String, 14); +array_patterns!(String, 15); +array_patterns!(String, 16); + #[cfg(feature = "http")] mod url; diff --git a/router/src/resource.rs b/router/src/resource.rs index 904655ac..8db1cfe2 100644 --- a/router/src/resource.rs +++ b/router/src/resource.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use regex::{escape, Regex, RegexSet}; use crate::path::{Path, PathItem}; -use crate::{IntoPatterns, Resource, ResourcePath}; +use crate::{IntoPattern, Resource, ResourcePath}; const MAX_DYNAMIC_SEGMENTS: usize = 16; @@ -39,24 +39,12 @@ impl ResourceDef { /// Parse path pattern and create new `Pattern` instance. /// /// Panics if path pattern is malformed. - pub fn new(path: T) -> Self { + pub fn new(path: T) -> Self { if path.is_single() { let patterns = path.patterns(); ResourceDef::with_prefix(&patterns[0], false) } else { - ResourceDef::new_set(path) - } - } - - /// Parse path pattern and create new `Pattern` instance. - /// - /// Panics if any of paths pattern is malformed. Every set element - /// must contain same set of capture elements. - pub fn new_set(set: T) -> Self { - if set.is_single() { - ResourceDef::new(set) - } else { - let set = set.patterns(); + let set = path.patterns(); let mut data = Vec::new(); let mut re_set = Vec::new(); @@ -709,7 +697,7 @@ mod tests { #[test] fn test_dynamic_set() { - let re = ResourceDef::new_set(vec![ + let re = ResourceDef::new(vec![ "/user/{id}", "/v{version}/resource/{id}", "/{id:[[:digit:]]{6}}", @@ -744,6 +732,26 @@ mod tests { let mut path = Path::new("/012345"); assert!(re.match_path(&mut path)); assert_eq!(path.get("id").unwrap(), "012345"); + + let re = ResourceDef::new([ + "/user/{id}", + "/v{version}/resource/{id}", + "/{id:[[:digit:]]{6}}", + ]); + assert!(re.is_match("/user/profile")); + assert!(re.is_match("/user/2345")); + assert!(!re.is_match("/user/2345/")); + assert!(!re.is_match("/user/2345/sdg")); + + let re = ResourceDef::new([ + "/user/{id}".to_string(), + "/v{version}/resource/{id}".to_string(), + "/{id:[[:digit:]]{6}}".to_string(), + ]); + assert!(re.is_match("/user/profile")); + assert!(re.is_match("/user/2345")); + assert!(!re.is_match("/user/2345/")); + assert!(!re.is_match("/user/2345/sdg")); } #[test]