1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-01-19 00:31:50 +01:00

introduce IntoPattern trait

This commit is contained in:
Nikolay Kim 2019-12-25 19:54:20 +04:00
parent bf0a9d2f6e
commit a2a9d9764d
4 changed files with 77 additions and 23 deletions

View File

@ -1,8 +1,8 @@
# Changes # Changes
## [0.2.1] - 2019-12-xx ## [0.2.1] - 2019-12-25
* Add `IntoPatterns` trait * Add `IntoPattern` trait
* Add multi-pattern resources * Add multi-pattern resources

View File

@ -492,7 +492,7 @@ mod tests {
#[derive(Deserialize)] #[derive(Deserialize)]
struct Id { struct Id {
id: String, _id: String,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]

View File

@ -36,14 +36,14 @@ impl ResourcePath for bytestring::ByteString {
} }
/// Helper trait for type that could be converted to path pattern /// Helper trait for type that could be converted to path pattern
pub trait IntoPatterns { pub trait IntoPattern {
/// Signle patter /// Signle patter
fn is_single(&self) -> bool; fn is_single(&self) -> bool;
fn patterns(&self) -> Vec<String>; fn patterns(&self) -> Vec<String>;
} }
impl IntoPatterns for String { impl IntoPattern for String {
fn is_single(&self) -> bool { fn is_single(&self) -> bool {
true 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 { fn is_single(&self) -> bool {
true true
} }
@ -63,7 +63,7 @@ impl<'a> IntoPatterns for &'a str {
} }
} }
impl<T: AsRef<str>> IntoPatterns for Vec<T> { impl<T: AsRef<str>> IntoPattern for Vec<T> {
fn is_single(&self) -> bool { fn is_single(&self) -> bool {
self.len() == 1 self.len() == 1
} }
@ -73,6 +73,52 @@ impl<T: AsRef<str>> IntoPatterns for Vec<T> {
} }
} }
macro_rules! array_patterns (($tp:ty, $num:tt) => {
impl IntoPattern for [$tp; $num] {
fn is_single(&self) -> bool {
$num == 1
}
fn patterns(&self) -> Vec<String> {
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")] #[cfg(feature = "http")]
mod url; mod url;

View File

@ -5,7 +5,7 @@ use std::rc::Rc;
use regex::{escape, Regex, RegexSet}; use regex::{escape, Regex, RegexSet};
use crate::path::{Path, PathItem}; use crate::path::{Path, PathItem};
use crate::{IntoPatterns, Resource, ResourcePath}; use crate::{IntoPattern, Resource, ResourcePath};
const MAX_DYNAMIC_SEGMENTS: usize = 16; const MAX_DYNAMIC_SEGMENTS: usize = 16;
@ -39,24 +39,12 @@ impl ResourceDef {
/// Parse path pattern and create new `Pattern` instance. /// Parse path pattern and create new `Pattern` instance.
/// ///
/// Panics if path pattern is malformed. /// Panics if path pattern is malformed.
pub fn new<T: IntoPatterns>(path: T) -> Self { pub fn new<T: IntoPattern>(path: T) -> Self {
if path.is_single() { if path.is_single() {
let patterns = path.patterns(); let patterns = path.patterns();
ResourceDef::with_prefix(&patterns[0], false) ResourceDef::with_prefix(&patterns[0], false)
} else { } else {
ResourceDef::new_set(path) let set = path.patterns();
}
}
/// 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<T: IntoPatterns>(set: T) -> Self {
if set.is_single() {
ResourceDef::new(set)
} else {
let set = set.patterns();
let mut data = Vec::new(); let mut data = Vec::new();
let mut re_set = Vec::new(); let mut re_set = Vec::new();
@ -709,7 +697,7 @@ mod tests {
#[test] #[test]
fn test_dynamic_set() { fn test_dynamic_set() {
let re = ResourceDef::new_set(vec![ let re = ResourceDef::new(vec![
"/user/{id}", "/user/{id}",
"/v{version}/resource/{id}", "/v{version}/resource/{id}",
"/{id:[[:digit:]]{6}}", "/{id:[[:digit:]]{6}}",
@ -744,6 +732,26 @@ mod tests {
let mut path = Path::new("/012345"); let mut path = Path::new("/012345");
assert!(re.match_path(&mut path)); assert!(re.match_path(&mut path));
assert_eq!(path.get("id").unwrap(), "012345"); 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] #[test]