From 6f4d2220fa06edf795113c8841a81799205174a3 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Fri, 4 Jun 2021 20:46:40 -0400 Subject: [PATCH] store Cow in actix-router Path (#345) --- actix-router/CHANGES.md | 3 ++- actix-router/src/path.rs | 33 ++++++++++++++++++++++---------- actix-router/src/resource.rs | 37 +++++++++++++----------------------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 4c19aedc..ade87b37 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -5,9 +5,10 @@ ## 0.2.7 - 2021-02-06 * Add `Router::recognize_checked` [#247] +* `Path::add` and `add_static` takes `impl Into>` [#345] [#247]: https://github.com/actix/actix-net/pull/247 - +[#345]: https://github.com/actix/actix-net/pull/345 ## 0.2.6 - 2021-01-09 * Use `bytestring` version range compatible with Bytes v1.0. [#246] diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index 76fd97da..6e4e2fdf 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ops::Index; use serde::de; @@ -5,12 +6,18 @@ use serde::de; use crate::de::PathDeserializer; use crate::{Resource, ResourcePath}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub(crate) enum PathItem { - Static(&'static str), + Static(Cow<'static, str>), Segment(u16, u16), } +impl Default for PathItem { + fn default() -> Self { + Self::Static(Cow::Borrowed("")) + } +} + /// Resource path match information /// /// If resource path contains variable patterns, `Path` stores them. @@ -18,7 +25,7 @@ pub(crate) enum PathItem { pub struct Path { path: T, pub(crate) skip: u16, - pub(crate) segments: Vec<(&'static str, PathItem)>, + pub(crate) segments: Vec<(Cow<'static, str>, PathItem)>, } impl Default for Path { @@ -95,18 +102,24 @@ impl Path { self.skip += n; } - pub(crate) fn add(&mut self, name: &'static str, value: PathItem) { + pub(crate) fn add(&mut self, name: impl Into>, value: PathItem) { match value { - PathItem::Static(s) => self.segments.push((name, PathItem::Static(s))), - PathItem::Segment(begin, end) => self - .segments - .push((name, PathItem::Segment(self.skip + begin, self.skip + end))), + PathItem::Static(s) => self.segments.push((name.into(), PathItem::Static(s))), + PathItem::Segment(begin, end) => self.segments.push(( + name.into(), + PathItem::Segment(self.skip + begin, self.skip + end), + )), } } #[doc(hidden)] - pub fn add_static(&mut self, name: &'static str, value: &'static str) { - self.segments.push((name, PathItem::Static(value))); + pub fn add_static( + &mut self, + name: impl Into>, + value: impl Into>, + ) { + self.segments + .push((name.into(), PathItem::Static(value.into()))); } /// Check if there are any matched patterns diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index 32162c53..9a3ffcb9 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -1,6 +1,7 @@ use std::cmp::min; use std::collections::HashMap; use std::hash::{Hash, Hasher}; +use std::mem; use regex::{escape, Regex, RegexSet}; @@ -272,15 +273,12 @@ impl ResourceDef { true } PatternType::Dynamic(ref re, ref names, len) => { - let mut idx = 0; let mut pos = 0; - let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = - [PathItem::Static(""); MAX_DYNAMIC_SEGMENTS]; + let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default(); if let Some(captures) = re.captures(path.path()) { for (no, name) in names.iter().enumerate() { if let Some(m) = captures.name(&name) { - idx += 1; pos = m.end(); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); } else { @@ -294,8 +292,8 @@ impl ResourceDef { } else { return false; } - for idx in 0..idx { - path.add(names[idx], segments[idx]); + for i in 0..names.len() { + path.add(names[i], mem::take(&mut segments[i])); } path.skip((pos + len) as u16); true @@ -303,15 +301,12 @@ impl ResourceDef { PatternType::DynamicSet(ref re, ref params) => { if let Some(idx) = re.matches(path.path()).into_iter().next() { let (ref pattern, ref names, len) = params[idx]; - let mut idx = 0; let mut pos = 0; - let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = - [PathItem::Static(""); MAX_DYNAMIC_SEGMENTS]; + let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default(); if let Some(captures) = pattern.captures(path.path()) { for (no, name) in names.iter().enumerate() { if let Some(m) = captures.name(&name) { - idx += 1; pos = m.end(); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); @@ -326,8 +321,8 @@ impl ResourceDef { } else { return false; } - for idx in 0..idx { - path.add(names[idx], segments[idx]); + for i in 0..names.len() { + path.add(names[i], mem::take(&mut segments[i])); } path.skip((pos + len) as u16); true @@ -385,15 +380,12 @@ impl ResourceDef { true } PatternType::Dynamic(ref re, ref names, len) => { - let mut idx = 0; let mut pos = 0; - let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = - [PathItem::Static(""); MAX_DYNAMIC_SEGMENTS]; + let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default(); if let Some(captures) = re.captures(res.resource_path().path()) { for (no, name) in names.iter().enumerate() { if let Some(m) = captures.name(&name) { - idx += 1; pos = m.end(); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); } else { @@ -413,8 +405,8 @@ impl ResourceDef { } let path = res.resource_path(); - for idx in 0..idx { - path.add(names[idx], segments[idx]); + for i in 0..names.len() { + path.add(names[i], mem::take(&mut segments[i])); } path.skip((pos + len) as u16); true @@ -423,15 +415,12 @@ impl ResourceDef { let path = res.resource_path().path(); if let Some(idx) = re.matches(path).into_iter().next() { let (ref pattern, ref names, len) = params[idx]; - let mut idx = 0; let mut pos = 0; - let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = - [PathItem::Static(""); MAX_DYNAMIC_SEGMENTS]; + let mut segments: [PathItem; MAX_DYNAMIC_SEGMENTS] = Default::default(); if let Some(captures) = pattern.captures(path) { for (no, name) in names.iter().enumerate() { if let Some(m) = captures.name(&name) { - idx += 1; pos = m.end(); segments[no] = PathItem::Segment(m.start() as u16, m.end() as u16); @@ -452,8 +441,8 @@ impl ResourceDef { } let path = res.resource_path(); - for idx in 0..idx { - path.add(names[idx], segments[idx]); + for i in 0..names.len() { + path.add(names[i], mem::take(&mut segments[i])); } path.skip((pos + len) as u16); true