mirror of https://github.com/fafhrd91/actix-net
rework IntoPatterns trait and codegen
This commit is contained in:
parent
a0fe2a9b2e
commit
5360b9eb58
|
@ -20,11 +20,12 @@ path = "src/lib.rs"
|
|||
default = ["http"]
|
||||
|
||||
[dependencies]
|
||||
bytestring = ">=0.1.5, <2"
|
||||
either = "1.6"
|
||||
http = { version = "0.2.3", optional = true }
|
||||
log = "0.4"
|
||||
regex = "1.5"
|
||||
serde = "1"
|
||||
bytestring = ">=0.1.5, <2"
|
||||
log = "0.4"
|
||||
http = { version = "0.2.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
http = "0.2.3"
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
use either::Either;
|
||||
|
||||
mod de;
|
||||
mod path;
|
||||
mod resource;
|
||||
|
@ -40,98 +42,64 @@ impl ResourcePath for bytestring::ByteString {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper trait for type that could be converted to path pattern
|
||||
pub trait IntoPattern {
|
||||
fn is_single(&self) -> bool;
|
||||
|
||||
fn patterns(&self) -> Vec<String>;
|
||||
/// Helper trait for type that could be converted to one or more path pattern.
|
||||
pub trait IntoPatterns {
|
||||
fn patterns(&self) -> Either<String, Vec<String>>;
|
||||
}
|
||||
|
||||
impl IntoPattern for String {
|
||||
fn is_single(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn patterns(&self) -> Vec<String> {
|
||||
vec![self.clone()]
|
||||
impl IntoPatterns for String {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
Either::Left(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPattern for &'a String {
|
||||
fn is_single(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn patterns(&self) -> Vec<String> {
|
||||
vec![self.as_str().to_string()]
|
||||
impl<'a> IntoPatterns for &'a String {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
Either::Left((*self).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPattern for &'a str {
|
||||
fn is_single(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn patterns(&self) -> Vec<String> {
|
||||
vec![(*self).to_string()]
|
||||
impl<'a> IntoPatterns for &'a str {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
Either::Left((*self).to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> IntoPattern for Vec<T> {
|
||||
fn is_single(&self) -> bool {
|
||||
self.len() == 1
|
||||
}
|
||||
impl<T: AsRef<str>> IntoPatterns for Vec<T> {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
let mut patterns = self.iter().map(|v| v.as_ref().to_owned());
|
||||
|
||||
fn patterns(&self) -> Vec<String> {
|
||||
self.iter().map(|v| v.as_ref().to_string()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array_patterns (($tp:ty, $num:tt) => {
|
||||
impl IntoPattern for [$tp; $num] {
|
||||
fn is_single(&self) -> bool {
|
||||
$num == 1
|
||||
match patterns.size_hint() {
|
||||
(1, _) => Either::Left(patterns.next().unwrap()),
|
||||
_ => Either::Right(patterns.collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn patterns(&self) -> Vec<String> {
|
||||
self.iter().map(|v| v.to_string()).collect()
|
||||
macro_rules! array_patterns_single (($tp:ty) => {
|
||||
impl IntoPatterns for [$tp; 1] {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
Either::Left(self[0].to_owned())
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
macro_rules! array_patterns_multiple (($tp:ty, $str_fn:expr, $($num:tt) +) => {
|
||||
// for each array length specified in $num
|
||||
$(
|
||||
impl IntoPatterns for [$tp; $num] {
|
||||
fn patterns(&self) -> Either<String, Vec<String>> {
|
||||
Either::Right(self.iter().map($str_fn).collect())
|
||||
}
|
||||
}
|
||||
)+
|
||||
});
|
||||
|
||||
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);
|
||||
array_patterns_single!(&str);
|
||||
array_patterns_multiple!(&str, |&v| v.to_owned(), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16);
|
||||
|
||||
array_patterns_single!(String);
|
||||
array_patterns_multiple!(String, |v| v.clone(), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16);
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
mod url;
|
||||
|
@ -140,10 +108,11 @@ mod url;
|
|||
pub use self::url::{Quoter, Url};
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
mod http_support {
|
||||
use super::ResourcePath;
|
||||
mod http_impls {
|
||||
use http::Uri;
|
||||
|
||||
use super::ResourcePath;
|
||||
|
||||
impl ResourcePath for Uri {
|
||||
fn path(&self) -> &str {
|
||||
self.path()
|
||||
|
|
|
@ -6,10 +6,11 @@ use std::{
|
|||
mem,
|
||||
};
|
||||
|
||||
use either::Either;
|
||||
use regex::{escape, Regex, RegexSet};
|
||||
|
||||
use crate::path::{Path, PathItem};
|
||||
use crate::{IntoPattern, Resource, ResourcePath};
|
||||
use crate::{IntoPatterns, Resource, ResourcePath};
|
||||
|
||||
const MAX_DYNAMIC_SEGMENTS: usize = 16;
|
||||
|
||||
|
@ -25,9 +26,6 @@ const REGEX_FLAGS: &str = "(?s-m)";
|
|||
pub struct ResourceDef {
|
||||
id: u16,
|
||||
|
||||
/// Pattern type.
|
||||
pat_type: PatternType,
|
||||
|
||||
/// Optional name of resource definition. Defaults to "".
|
||||
name: String,
|
||||
|
||||
|
@ -35,6 +33,9 @@ pub struct ResourceDef {
|
|||
// TODO: Sort of, in dynamic set pattern type it is blank, consider change to option.
|
||||
pattern: String,
|
||||
|
||||
/// Pattern type.
|
||||
pat_type: PatternType,
|
||||
|
||||
/// List of elements that compose the pattern, in order.
|
||||
///
|
||||
/// `None` with pattern type is DynamicSet.
|
||||
|
@ -75,29 +76,45 @@ impl ResourceDef {
|
|||
/// Parse path pattern and create new `Pattern` instance.
|
||||
///
|
||||
/// Panics if path pattern is malformed.
|
||||
pub fn new<T: IntoPattern>(path: T) -> Self {
|
||||
if path.is_single() {
|
||||
ResourceDef::from_single_pattern(&path.patterns()[0], false)
|
||||
} else {
|
||||
let mut data = Vec::new();
|
||||
let mut re_set = Vec::new();
|
||||
pub fn new<T: IntoPatterns>(path: T) -> Self {
|
||||
match path.patterns() {
|
||||
Either::Left(pattern) => ResourceDef::from_single_pattern(&pattern, false),
|
||||
|
||||
for pattern in path.patterns() {
|
||||
match ResourceDef::parse(&pattern, false, true) {
|
||||
(PatternType::Dynamic(re, names), _) => {
|
||||
re_set.push(re.as_str().to_owned());
|
||||
data.push((re, names));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
Either::Right(patterns) => {
|
||||
if patterns.is_empty() {
|
||||
// since zero length pattern sets are possible, return a useless `ResourceDef`
|
||||
|
||||
return ResourceDef {
|
||||
id: 0,
|
||||
name: String::new(),
|
||||
pattern: String::new(),
|
||||
pat_type: PatternType::DynamicSet(RegexSet::empty(), Vec::new()),
|
||||
elements: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ResourceDef {
|
||||
id: 0,
|
||||
pat_type: PatternType::DynamicSet(RegexSet::new(re_set).unwrap(), data),
|
||||
elements: None,
|
||||
name: String::new(),
|
||||
pattern: "".to_owned(),
|
||||
let mut re_set = Vec::with_capacity(patterns.len());
|
||||
let mut pattern_data = Vec::new();
|
||||
|
||||
for pattern in patterns {
|
||||
match ResourceDef::parse(&pattern, false, true) {
|
||||
(PatternType::Dynamic(re, names), _) => {
|
||||
re_set.push(re.as_str().to_owned());
|
||||
pattern_data.push((re, names));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
let pattern_re_set = RegexSet::new(re_set).unwrap();
|
||||
|
||||
ResourceDef {
|
||||
id: 0,
|
||||
name: String::new(),
|
||||
pattern: String::new(),
|
||||
pat_type: PatternType::DynamicSet(pattern_re_set, pattern_data),
|
||||
elements: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{IntoPattern, Resource, ResourceDef, ResourcePath};
|
||||
use crate::{IntoPatterns, Resource, ResourceDef, ResourcePath};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct ResourceId(pub u16);
|
||||
|
@ -88,7 +88,7 @@ pub struct RouterBuilder<T, U = ()> {
|
|||
|
||||
impl<T, U> RouterBuilder<T, U> {
|
||||
/// Register resource for specified path.
|
||||
pub fn path<P: IntoPattern>(
|
||||
pub fn path<P: IntoPatterns>(
|
||||
&mut self,
|
||||
path: P,
|
||||
resource: T,
|
||||
|
|
Loading…
Reference in New Issue