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) => { diff --git a/contrib/src/templates/tera_templates.rs b/contrib/src/templates/tera_templates.rs index a580866b..863e86b1 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 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/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/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| { 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 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) }