From dda6ee95dff239a386cb7d6d8f052b21545e1875 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 22 Jun 2018 09:33:32 +0200 Subject: [PATCH] Changes the router to use atoms internally (#341) --- Cargo.toml | 7 ++++--- src/lib.rs | 1 + src/param.rs | 23 ++++++++++++----------- src/router.rs | 20 ++++++++------------ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 787ade1e..e60d0793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ license = "MIT/Apache-2.0" exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] build = "build.rs" +[package.metadata.docs.rs] +features = ["tls", "alpn", "session", "brotli", "flate2-c"] + [badges] travis-ci = { repository = "actix/actix-web", branch = "master" } appveyor = { repository = "fafhrd91/actix-web-hdy9d" } @@ -46,9 +49,6 @@ flate2-c = ["flate2/miniz-sys"] # rust backend for flate2 crate flate2-rust = ["flate2/rust_backend"] -[package.metadata.docs.rs] -features = ["tls", "alpn", "session", "brotli", "flate2-c"] - [dependencies] # actix = "0.6.1" actix = { git="https://github.com/actix/actix.git" } @@ -103,6 +103,7 @@ tokio-tls = { version="0.1", optional = true } # openssl openssl = { version="0.10", optional = true } tokio-openssl = { version="0.2", optional = true } +string_cache = "0.7.3" [dev-dependencies] env_logger = "0.5" diff --git a/src/lib.rs b/src/lib.rs index 7cb2b908..5c7bfbac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,6 +114,7 @@ extern crate net2; extern crate parking_lot; extern crate rand; extern crate slab; +extern crate string_cache; extern crate tokio; extern crate tokio_io; extern crate tokio_reactor; diff --git a/src/param.rs b/src/param.rs index 1329ff68..54325ee1 100644 --- a/src/param.rs +++ b/src/param.rs @@ -5,6 +5,7 @@ use std::str::FromStr; use http::StatusCode; use smallvec::SmallVec; +use string_cache::DefaultAtom as Atom; use error::{InternalError, ResponseError, UriSegmentError}; use uri::Url; @@ -19,9 +20,9 @@ pub trait FromParam: Sized { fn from_param(s: &str) -> Result; } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub(crate) enum ParamItem { - Static(&'static str), + Static(Atom), UrlSegment(u16, u16), } @@ -32,7 +33,7 @@ pub(crate) enum ParamItem { pub struct Params { url: Url, pub(crate) tail: u16, - segments: SmallVec<[(&'static str, ParamItem); 3]>, + segments: SmallVec<[(Atom, ParamItem); 3]>, } impl Params { @@ -56,12 +57,12 @@ impl Params { self.tail = tail; } - pub(crate) fn add(&mut self, name: &'static str, value: ParamItem) { + pub(crate) fn add(&mut self, name: Atom, value: ParamItem) { self.segments.push((name, value)); } - pub(crate) fn add_static(&mut self, name: &'static str, value: &'static str) { - self.segments.push((name, ParamItem::Static(value))); + pub(crate) fn add_static(&mut self, name: &str, value: &'static str) { + self.segments.push((Atom::from(name), ParamItem::Static(Atom::from(value)))); } /// Check if there are any matched patterns @@ -77,9 +78,9 @@ impl Params { /// Get matched parameter by name without type conversion pub fn get(&self, key: &str) -> Option<&str> { for item in self.segments.iter() { - if key == item.0 { + if key == &item.0 { return match item.1 { - ParamItem::Static(s) => Some(s), + ParamItem::Static(ref s) => Some(&s), ParamItem::UrlSegment(s, e) => { Some(&self.url.path()[(s as usize)..(e as usize)]) } @@ -138,13 +139,13 @@ impl<'a> Iterator for ParamsIter<'a> { if self.idx < self.params.len() { let idx = self.idx; let res = match self.params.segments[idx].1 { - ParamItem::Static(s) => s, + ParamItem::Static(ref s) => &s, ParamItem::UrlSegment(s, e) => { &self.params.url.path()[(s as usize)..(e as usize)] } }; self.idx += 1; - return Some((self.params.segments[idx].0, res)); + return Some((&self.params.segments[idx].0, res)); } None } @@ -164,7 +165,7 @@ impl<'a> Index for &'a Params { fn index(&self, idx: usize) -> &str { match self.segments[idx].1 { - ParamItem::Static(s) => s, + ParamItem::Static(ref s) => &s, ParamItem::UrlSegment(s, e) => &self.url.path()[(s as usize)..(e as usize)], } } diff --git a/src/router.rs b/src/router.rs index 9aa173f7..03e299e1 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; use std::hash::{Hash, Hasher}; -use std::mem; use std::rc::Rc; use regex::{escape, Regex}; @@ -12,6 +11,8 @@ use param::ParamItem; use resource::ResourceHandler; use server::ServerSettings; +use string_cache::DefaultAtom as Atom; + /// Interface for application router. pub struct Router(Rc); @@ -144,7 +145,7 @@ enum PatternElement { enum PatternType { Static(String), Prefix(String), - Dynamic(Regex, Vec<&'static str>, usize), + Dynamic(Regex, Vec, usize), } #[derive(Debug, Copy, Clone, PartialEq)] @@ -221,12 +222,7 @@ impl Resource { let names = re .capture_names() .filter_map(|name| { - name.map(|name| { - let name = name.to_owned(); - let s: &'static str = unsafe { mem::transmute(name.as_str()) }; - mem::forget(name); - s - }) + name.map(|name| Atom::from(name)) }) .collect(); PatternType::Dynamic(re, names, len) @@ -316,8 +312,8 @@ impl Resource { let len = req.path().len(); let params = req.match_info_mut(); params.set_tail(len as u16); - for (idx, segment) in segments.iter().enumerate() { - params.add(names[idx], *segment); + for (idx, segment) in segments.into_iter().enumerate() { + params.add(names[idx].clone(), segment); } true } @@ -382,8 +378,8 @@ impl Resource { let params = req.match_info_mut(); params.set_tail(tail_len as u16); - for (idx, segment) in segments.iter().enumerate() { - params.add(names[idx], *segment); + for (idx, segment) in segments.into_iter().enumerate() { + params.add(names[idx].clone(), segment); } Some(tail_len) }