From 3abc81360539cc4a08a381cce2baade138dee4b5 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Fri, 21 Jul 2017 17:00:38 -0400 Subject: [PATCH 1/5] Use 'AtomicIsize', not 'Cell', in URI. --- lib/src/http/uri.rs | 60 ++++++++++++++++++++++++++++++++++++--------- lib/src/rocket.rs | 1 - 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/lib/src/http/uri.rs b/lib/src/http/uri.rs index 20b990ec..eeac2335 100644 --- a/lib/src/http/uri.rs +++ b/lib/src/http/uri.rs @@ -1,25 +1,29 @@ //! Borrowed and owned string types for absolute URIs. -use std::cell::Cell; use std::convert::From; use std::fmt; use std::borrow::Cow; use std::str::Utf8Error; +use std::sync::atomic::{AtomicIsize, Ordering}; use url; /// Index (start, end) into a string, to prevent borrowing. type Index = (usize, usize); +/// Representation of an empty segment count. +const EMPTY: isize = -1; + // TODO: Reconsider deriving PartialEq and Eq to make "//a/b" == "/a/b". /// Borrowed string type for absolute URIs. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug)] pub struct URI<'a> { uri: Cow<'a, str>, path: Index, query: Option, fragment: Option, - segment_count: Cell>, + // The cached segment count. `EMPTY` is used to represent no segment count. + segment_count: AtomicIsize, } impl<'a> URI<'a> { @@ -43,7 +47,7 @@ impl<'a> URI<'a> { path: path, query: query, fragment: fragment, - segment_count: Cell::new(None), + segment_count: AtomicIsize::new(EMPTY), } } @@ -74,11 +78,17 @@ impl<'a> URI<'a> { /// ``` #[inline(always)] pub fn segment_count(&self) -> usize { - self.segment_count.get().unwrap_or_else(|| { - let count = self.segments().count(); - self.segment_count.set(Some(count)); - count - }) + let count = self.segment_count.load(Ordering::Relaxed); + if count == EMPTY { + let real_count = self.segments().count(); + if real_count <= isize::max_value() as usize { + self.segment_count.store(real_count as isize, Ordering::Relaxed); + } + + real_count + } else { + count as usize + } } /// Returns an iterator over the segments of the path in this URI. Skips @@ -275,6 +285,30 @@ impl<'a> URI<'a> { } } +impl<'a> Clone for URI<'a> { + #[inline(always)] + fn clone(&self) -> URI<'a> { + URI { + uri: self.uri.clone(), + path: self.path, + query: self.query, + fragment: self.fragment, + segment_count: AtomicIsize::new(EMPTY), + } + } +} + +impl<'a, 'b> PartialEq> for URI<'a> { + #[inline] + fn eq(&self, other: &URI<'b>) -> bool { + self.path() == other.path() && + self.query() == other.query() && + self.fragment() == other.fragment() + } +} + +impl<'a> Eq for URI<'a> {} + impl<'a> From<&'a str> for URI<'a> { #[inline(always)] fn from(uri: &'a str) -> URI<'a> { @@ -312,8 +346,6 @@ impl<'a> fmt::Display for URI<'a> { } } -unsafe impl<'a> Sync for URI<'a> { /* It's safe! */ } - /// Iterator over the segments of an absolute URI path. Skips empty segments. /// /// ### Examples @@ -405,6 +437,12 @@ mod tests { actual == expected } + #[test] + fn send_and_sync() { + fn assert() {}; + assert::(); + } + #[test] fn simple_segment_count() { assert!(seg_count("", 0)); diff --git a/lib/src/rocket.rs b/lib/src/rocket.rs index 1c99410a..1fdf58c1 100644 --- a/lib/src/rocket.rs +++ b/lib/src/rocket.rs @@ -72,7 +72,6 @@ impl hyper::Handler for Rocket { }; // Dispatch the request to get a response, then write that response out. - // let req = UnsafeCell::new(req); let response = self.dispatch(&mut req, data); self.issue_response(response, res) } From b276e1d51fca2b794c62ce605f7f62bb079ef9ed Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Wed, 26 Jul 2017 22:41:01 -0400 Subject: [PATCH 2/5] Enable ASCII escape sequences in Windows consoles. --- lib/Cargo.toml | 2 +- lib/src/logger.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 5ce4c8fb..cb857fe1 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -18,7 +18,7 @@ categories = ["web-programming::http-server"] tls = ["rustls", "hyper-sync-rustls"] [dependencies] -yansi = { version = "0.3", features = ["nightly"] } +yansi = { version = "0.3.1", features = ["nightly"] } log = "0.3" url = "1" toml = "0.4.2" diff --git a/lib/src/logger.rs b/lib/src/logger.rs index 5e61bc39..6c9b61ad 100644 --- a/lib/src/logger.rs +++ b/lib/src/logger.rs @@ -143,6 +143,8 @@ impl Log for RocketLogger { pub fn try_init(level: LoggingLevel, verbose: bool) { if !::isatty::stdout_isatty() { Paint::disable(); + } else if cfg!(windows) { + Paint::enable_windows_ascii(); } let result = log::set_logger(|max_log_level| { From 5f0583eb049892f9795be1fc66134842c37ff88a Mon Sep 17 00:00:00 2001 From: Laurentiu Nicola Date: Tue, 25 Jul 2017 21:52:04 +0300 Subject: [PATCH 3/5] Don't skip over the first Tera error. The first line in the Tera error messages is sometimes less useful, but in other cases, like when the context is not a map or struct, contains the complete description. As such, always include it, even if the output is slightly uglier. Also don't append periods at the end since some Tera messages already have them. --- contrib/src/templates/tera_templates.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/src/templates/tera_templates.rs b/contrib/src/templates/tera_templates.rs index f4fb9892..1351d3e7 100644 --- a/contrib/src/templates/tera_templates.rs +++ b/contrib/src/templates/tera_templates.rs @@ -41,8 +41,8 @@ impl Engine for Tera { Ok(string) => Some(string), Err(e) => { error_!("Error rendering Tera template '{}'.", name); - for error in e.iter().skip(1) { - error_!("{}.", error); + for error in e.iter() { + error_!("{}", error); } None From 02794db2cd6646d21cd834e99c3e86e2a600ddb2 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 25 Jul 2017 19:28:34 -0400 Subject: [PATCH 4/5] Allow unreachable patterns in generated matches. --- codegen/src/decorators/route.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codegen/src/decorators/route.rs b/codegen/src/decorators/route.rs index 37256036..904734f5 100644 --- a/codegen/src/decorators/route.rs +++ b/codegen/src/decorators/route.rs @@ -77,6 +77,7 @@ impl RouteGenerateExt for RouteParams { let $name: $ty = { let mut items = ::rocket::request::FormItems::from($form_string); let form = ::rocket::request::FromForm::from_form(items.by_ref(), true); + #[allow(unreachable_patterns)] let obj = match form { Ok(v) => v, Err(_) => return ::rocket::Outcome::Forward(__data) @@ -162,6 +163,7 @@ impl RouteGenerateExt for RouteParams { let original_ident = param.ident(); fn_param_statements.push(quote_stmt!(ecx, + #[allow(unreachable_patterns)] let $ident: $ty = match $expr { Ok(v) => v, Err(e) => { From 84fe23a9fb10b06a9f25eebf28345855ddd0ce72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ian=20L=C3=A9tourneau?= Date: Fri, 21 Jul 2017 21:35:44 -0400 Subject: [PATCH 5/5] Fix spelling of "corresponding" in 'status' docs. --- lib/src/response/status.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/response/status.rs b/lib/src/response/status.rs index f09ce744..1aca4be7 100644 --- a/lib/src/response/status.rs +++ b/lib/src/response/status.rs @@ -1,4 +1,4 @@ -//! Contains types that set the status code and correspoding headers of a +//! Contains types that set the status code and corresponding headers of a //! response. //! //! These types are designed to make it easier to respond correctly with a given