diff --git a/router/CHANGES.txt b/router/CHANGES.txt index 1898c253..c9283566 100644 --- a/router/CHANGES.txt +++ b/router/CHANGES.txt @@ -1,8 +1,6 @@ # Changes -## [0.3.0] - 2019-12-31 - -* Support named parameters for `ResourceDef::resource_path()` in form of `((&k, &v), ...)` +## [0.2.4] - 2019-12-xx ## [0.2.3] - 2019-12-25 diff --git a/router/Cargo.toml b/router/Cargo.toml index 19b5bd01..1e5f4d54 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-router" -version = "0.3.0" +version = "0.2.4" authors = ["Nikolay Kim "] description = "Path router" keywords = ["actix"] @@ -18,11 +18,10 @@ path = "src/lib.rs" default = ["http"] [dependencies] -bytestring = "0.1.2" -either = "1.5.3" regex = "1.3.1" -log = "0.4.8" serde = "1.0.104" +bytestring = "0.1.2" +log = "0.4.8" http = { version="0.2.0", optional=true } [dev-dependencies] diff --git a/router/src/lib.rs b/router/src/lib.rs index ab4d1658..7e41c4c3 100644 --- a/router/src/lib.rs +++ b/router/src/lib.rs @@ -4,8 +4,6 @@ mod path; mod resource; mod router; -use either::Either; - pub use self::de::PathDeserializer; pub use self::path::Path; pub use self::resource::ResourceDef; @@ -37,127 +35,6 @@ impl ResourcePath for bytestring::ByteString { } } -pub trait ResourceElements { - fn elements(self, for_each: F) -> Option - where - F: FnMut(Either<&str, (&str, &str)>) -> Option; -} - -impl<'a, T: AsRef> ResourceElements for &'a [T] { - fn elements(self, mut for_each: F) -> Option - where - F: FnMut(Either<&str, (&str, &str)>) -> Option, - { - for t in self { - if let Some(res) = for_each(Either::Left(t.as_ref())) { - return Some(res); - } - } - None - } -} - -impl<'a, U, I> ResourceElements for &'a U -where - &'a U: IntoIterator, - I: AsRef, -{ - fn elements(self, mut for_each: F) -> Option - where - F: FnMut(Either<&str, (&str, &str)>) -> Option, - { - for t in self.into_iter() { - if let Some(res) = for_each(Either::Left(t.as_ref())) { - return Some(res); - } - } - None - } -} - -impl ResourceElements for Vec -where - I: AsRef, -{ - fn elements(self, mut for_each: F) -> Option - where - F: FnMut(Either<&str, (&str, &str)>) -> Option, - { - for t in self.iter() { - if let Some(res) = for_each(Either::Left(t.as_ref())) { - return Some(res); - } - } - None - } -} - -impl<'a, K, V, S> ResourceElements for std::collections::HashMap -where - K: AsRef, - V: AsRef, - S: std::hash::BuildHasher, -{ - fn elements(self, mut for_each: F) -> Option - where - F: FnMut(Either<&str, (&str, &str)>) -> Option, - { - for t in self.iter() { - if let Some(res) = for_each(Either::Right((t.0.as_ref(), t.1.as_ref()))) { - return Some(res); - } - } - None - } -} - -#[rustfmt::skip] -mod _m { -use super::*; -// macro_rules! elements_tuple ({ $(($n:tt, $T:ident)),+} => { -// impl<$($T: AsRef,)+> ResourceElements for ($($T,)+) { -// fn elements(self, mut for_each: F_) -> Option -// where -// F_: FnMut(Either<&str, (&str, &str)>) -> Option, -// { -// $( -// if let Some(res) = for_each(Either::Left(self.$n.as_ref())) { -// return Some(res) -// } -// )+ -// None -// } -// } -// }); - -macro_rules! elements_2tuple ({ $(($n:tt, $V:ident)),+} => { - impl<'a, $($V: AsRef,)+> ResourceElements for ($((&'a str, $V),)+) { - fn elements(self, mut for_each: F_) -> Option - where - F_: FnMut(Either<&str, (&str, &str)>) -> Option, - { - $( - if let Some(res) = for_each(Either::Right((self.$n.0, self.$n.1.as_ref()))) { - return Some(res) - } - )+ - None - } - } -}); - -elements_2tuple!((0, A)); -elements_2tuple!((0, A), (1, B)); -elements_2tuple!((0, A), (1, B), (2, C)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I)); -elements_2tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J)); -} - /// Helper trait for type that could be converted to path pattern pub trait IntoPattern { /// Signle patter diff --git a/router/src/resource.rs b/router/src/resource.rs index 84e772da..999bedfe 100644 --- a/router/src/resource.rs +++ b/router/src/resource.rs @@ -1,11 +1,10 @@ use std::cmp::min; -use std::collections::HashMap; use std::hash::{Hash, Hasher}; use regex::{escape, Regex, RegexSet}; use crate::path::{Path, PathItem}; -use crate::{IntoPattern, Resource, ResourceElements, ResourcePath}; +use crate::{IntoPattern, Resource, ResourcePath}; const MAX_DYNAMIC_SEGMENTS: usize = 16; @@ -464,66 +463,26 @@ impl ResourceDef { } /// Build resource path from elements. Returns `true` on success. - pub fn resource_path(&self, path: &mut String, data: U) -> bool { + pub fn resource_path(&self, path: &mut String, elements: &mut U) -> bool + where + U: Iterator, + I: AsRef, + { match self.tp { PatternType::Prefix(ref p) => path.push_str(p), PatternType::Static(ref p) => path.push_str(p), PatternType::Dynamic(..) => { - let mut iter = self.elements.iter(); - let mut map = HashMap::new(); - - let result = data.elements(|item| match item { - either::Either::Left(val) => loop { - if let Some(el) = iter.next() { - match *el { - PatternElement::Str(ref s) => path.push_str(s), - PatternElement::Var(_) => { - path.push_str(val.as_ref()); - return None; - } - } - } else { - return Some(false); - } - }, - either::Either::Right((name, val)) => { - map.insert(name.to_string(), val.to_string()); - None - } - }); - - if result.is_some() { - return true; - } else { - if map.is_empty() { - // push static sections - loop { - if let Some(el) = iter.next() { - match *el { - PatternElement::Str(ref s) => path.push_str(s), - PatternElement::Var(_) => { - return false; - } - } + for el in &self.elements { + match *el { + PatternElement::Str(ref s) => path.push_str(s), + PatternElement::Var(_) => { + if let Some(val) = elements.next() { + path.push_str(val.as_ref()) } else { - break; - } - } - } else { - for el in iter { - match *el { - PatternElement::Str(ref s) => path.push_str(s), - PatternElement::Var(ref name) => { - if let Some(val) = map.get(name) { - path.push_str(val); - continue; - } - return false; - } + return false; } } } - return true; } } PatternType::DynamicSet(..) => { @@ -673,7 +632,6 @@ pub(crate) fn insert_slash(path: &str) -> String { mod tests { use super::*; use http::Uri; - use std::collections::HashMap; use std::convert::TryFrom; #[test] @@ -900,71 +858,4 @@ mod tests { assert_eq!(&path["name"], "test2"); assert_eq!(&path[0], "test2"); } - - #[test] - fn test_resource_path() { - let mut s = String::new(); - let resource = ResourceDef::new("/user/{item1}/test"); - assert!(resource.resource_path(&mut s, &["user1"])); - assert_eq!(s, "/user/user1/test"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, (("item1", "user1"),))); - assert_eq!(s, "/user/user1/test"); - - let mut s = String::new(); - let resource = ResourceDef::new("/user/{item1}/{item2}/test"); - assert!(resource.resource_path(&mut s, &["item", "item2"])); - assert_eq!(s, "/user/item/item2/test"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, (("item1", "item"), ("item2", "item2")))); - assert_eq!(s, "/user/item/item2/test"); - - let mut s = String::new(); - let resource = ResourceDef::new("/user/{item1}/{item2}"); - assert!(resource.resource_path(&mut s, &["item", "item2"])); - assert_eq!(s, "/user/item/item2"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, (("item1", "item"), ("item2", "item2")))); - assert_eq!(s, "/user/item/item2"); - - let mut s = String::new(); - let resource = ResourceDef::new("/user/{item1}/{item2}/"); - assert!(resource.resource_path(&mut s, &["item", "item2"])); - assert_eq!(s, "/user/item/item2/"); - - let mut s = String::new(); - assert!(!resource.resource_path(&mut s, &["item"])); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, &["item", "item2"])); - assert_eq!(s, "/user/item/item2/"); - assert!(!resource.resource_path(&mut s, &["item"])); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, vec!["item", "item2"])); - assert_eq!(s, "/user/item/item2/"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, &vec!["item", "item2"])); - assert_eq!(s, "/user/item/item2/"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, &vec!["item", "item2"][..])); - assert_eq!(s, "/user/item/item2/"); - - let mut map = HashMap::new(); - map.insert("item1", "item"); - map.insert("item2", "item2"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, map)); - assert_eq!(s, "/user/item/item2/"); - - let mut s = String::new(); - assert!(resource.resource_path(&mut s, (("item1", "item"), ("item2", "item2")))); - assert_eq!(s, "/user/item/item2/"); - } }