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

store Cow in actix-router Path (#345)

This commit is contained in:
Ibraheem Ahmed 2021-06-04 20:46:40 -04:00 committed by GitHub
parent 54b22f9fce
commit 6f4d2220fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 35 deletions

View File

@ -5,9 +5,10 @@
## 0.2.7 - 2021-02-06 ## 0.2.7 - 2021-02-06
* Add `Router::recognize_checked` [#247] * Add `Router::recognize_checked` [#247]
* `Path::add` and `add_static` takes `impl Into<Cow<'static, str>>` [#345]
[#247]: https://github.com/actix/actix-net/pull/247 [#247]: https://github.com/actix/actix-net/pull/247
[#345]: https://github.com/actix/actix-net/pull/345
## 0.2.6 - 2021-01-09 ## 0.2.6 - 2021-01-09
* Use `bytestring` version range compatible with Bytes v1.0. [#246] * Use `bytestring` version range compatible with Bytes v1.0. [#246]

View File

@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::ops::Index; use std::ops::Index;
use serde::de; use serde::de;
@ -5,12 +6,18 @@ use serde::de;
use crate::de::PathDeserializer; use crate::de::PathDeserializer;
use crate::{Resource, ResourcePath}; use crate::{Resource, ResourcePath};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone)]
pub(crate) enum PathItem { pub(crate) enum PathItem {
Static(&'static str), Static(Cow<'static, str>),
Segment(u16, u16), Segment(u16, u16),
} }
impl Default for PathItem {
fn default() -> Self {
Self::Static(Cow::Borrowed(""))
}
}
/// Resource path match information /// Resource path match information
/// ///
/// If resource path contains variable patterns, `Path` stores them. /// If resource path contains variable patterns, `Path` stores them.
@ -18,7 +25,7 @@ pub(crate) enum PathItem {
pub struct Path<T> { pub struct Path<T> {
path: T, path: T,
pub(crate) skip: u16, pub(crate) skip: u16,
pub(crate) segments: Vec<(&'static str, PathItem)>, pub(crate) segments: Vec<(Cow<'static, str>, PathItem)>,
} }
impl<T: Default> Default for Path<T> { impl<T: Default> Default for Path<T> {
@ -95,18 +102,24 @@ impl<T: ResourcePath> Path<T> {
self.skip += n; self.skip += n;
} }
pub(crate) fn add(&mut self, name: &'static str, value: PathItem) { pub(crate) fn add(&mut self, name: impl Into<Cow<'static, str>>, value: PathItem) {
match value { match value {
PathItem::Static(s) => self.segments.push((name, PathItem::Static(s))), PathItem::Static(s) => self.segments.push((name.into(), PathItem::Static(s))),
PathItem::Segment(begin, end) => self PathItem::Segment(begin, end) => self.segments.push((
.segments name.into(),
.push((name, PathItem::Segment(self.skip + begin, self.skip + end))), PathItem::Segment(self.skip + begin, self.skip + end),
)),
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub fn add_static(&mut self, name: &'static str, value: &'static str) { pub fn add_static(
self.segments.push((name, PathItem::Static(value))); &mut self,
name: impl Into<Cow<'static, str>>,
value: impl Into<Cow<'static, str>>,
) {
self.segments
.push((name.into(), PathItem::Static(value.into())));
} }
/// Check if there are any matched patterns /// Check if there are any matched patterns

View File

@ -1,6 +1,7 @@
use std::cmp::min; use std::cmp::min;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::mem;
use regex::{escape, Regex, RegexSet}; use regex::{escape, Regex, RegexSet};
@ -272,15 +273,12 @@ impl ResourceDef {
true true
} }
PatternType::Dynamic(ref re, ref names, len) => { PatternType::Dynamic(ref re, ref names, len) => {
let mut idx = 0;
let mut pos = 0; let mut pos = 0;
let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default();
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
if let Some(captures) = re.captures(path.path()) { if let Some(captures) = re.captures(path.path()) {
for (no, name) in names.iter().enumerate() { for (no, name) in names.iter().enumerate() {
if let Some(m) = captures.name(&name) { if let Some(m) = captures.name(&name) {
idx += 1;
pos = m.end(); pos = m.end();
segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16);
} else { } else {
@ -294,8 +292,8 @@ impl ResourceDef {
} else { } else {
return false; return false;
} }
for idx in 0..idx { for i in 0..names.len() {
path.add(names[idx], segments[idx]); path.add(names[i], mem::take(&mut segments[i]));
} }
path.skip((pos + len) as u16); path.skip((pos + len) as u16);
true true
@ -303,15 +301,12 @@ impl ResourceDef {
PatternType::DynamicSet(ref re, ref params) => { PatternType::DynamicSet(ref re, ref params) => {
if let Some(idx) = re.matches(path.path()).into_iter().next() { if let Some(idx) = re.matches(path.path()).into_iter().next() {
let (ref pattern, ref names, len) = params[idx]; let (ref pattern, ref names, len) = params[idx];
let mut idx = 0;
let mut pos = 0; let mut pos = 0;
let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default();
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
if let Some(captures) = pattern.captures(path.path()) { if let Some(captures) = pattern.captures(path.path()) {
for (no, name) in names.iter().enumerate() { for (no, name) in names.iter().enumerate() {
if let Some(m) = captures.name(&name) { if let Some(m) = captures.name(&name) {
idx += 1;
pos = m.end(); pos = m.end();
segments[no] = segments[no] =
PathItem::Segment(m.start() as u16, m.end() as u16); PathItem::Segment(m.start() as u16, m.end() as u16);
@ -326,8 +321,8 @@ impl ResourceDef {
} else { } else {
return false; return false;
} }
for idx in 0..idx { for i in 0..names.len() {
path.add(names[idx], segments[idx]); path.add(names[i], mem::take(&mut segments[i]));
} }
path.skip((pos + len) as u16); path.skip((pos + len) as u16);
true true
@ -385,15 +380,12 @@ impl ResourceDef {
true true
} }
PatternType::Dynamic(ref re, ref names, len) => { PatternType::Dynamic(ref re, ref names, len) => {
let mut idx = 0;
let mut pos = 0; let mut pos = 0;
let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default();
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
if let Some(captures) = re.captures(res.resource_path().path()) { if let Some(captures) = re.captures(res.resource_path().path()) {
for (no, name) in names.iter().enumerate() { for (no, name) in names.iter().enumerate() {
if let Some(m) = captures.name(&name) { if let Some(m) = captures.name(&name) {
idx += 1;
pos = m.end(); pos = m.end();
segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16);
} else { } else {
@ -413,8 +405,8 @@ impl ResourceDef {
} }
let path = res.resource_path(); let path = res.resource_path();
for idx in 0..idx { for i in 0..names.len() {
path.add(names[idx], segments[idx]); path.add(names[i], mem::take(&mut segments[i]));
} }
path.skip((pos + len) as u16); path.skip((pos + len) as u16);
true true
@ -423,15 +415,12 @@ impl ResourceDef {
let path = res.resource_path().path(); let path = res.resource_path().path();
if let Some(idx) = re.matches(path).into_iter().next() { if let Some(idx) = re.matches(path).into_iter().next() {
let (ref pattern, ref names, len) = params[idx]; let (ref pattern, ref names, len) = params[idx];
let mut idx = 0;
let mut pos = 0; let mut pos = 0;
let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default();
[PathItem::Static(""); MAX_DYNAMIC_SEGMENTS];
if let Some(captures) = pattern.captures(path) { if let Some(captures) = pattern.captures(path) {
for (no, name) in names.iter().enumerate() { for (no, name) in names.iter().enumerate() {
if let Some(m) = captures.name(&name) { if let Some(m) = captures.name(&name) {
idx += 1;
pos = m.end(); pos = m.end();
segments[no] = segments[no] =
PathItem::Segment(m.start() as u16, m.end() as u16); PathItem::Segment(m.start() as u16, m.end() as u16);
@ -452,8 +441,8 @@ impl ResourceDef {
} }
let path = res.resource_path(); let path = res.resource_path();
for idx in 0..idx { for i in 0..names.len() {
path.add(names[idx], segments[idx]); path.add(names[i], mem::take(&mut segments[i]));
} }
path.skip((pos + len) as u16); path.skip((pos + len) as u16);
true true