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