Don't implement 'UriDisplay' for all 'T: Display'.

We don't know if that 'Display' implementation is URI safe, so using
it blindly could result in generating bad URIs.
This commit is contained in:
Sergio Benitez 2017-09-11 02:27:23 -07:00
parent f623d92484
commit 909eae894a
2 changed files with 41 additions and 10 deletions

View File

@ -18,7 +18,7 @@ impl<'a> FromParam<'a> for S {
fn simple(id: i32) -> &'static str { "" } fn simple(id: i32) -> &'static str { "" }
#[post("/<id>/<name>")] #[post("/<id>/<name>")]
//~^ ERROR the trait bound `S: std::fmt::Display` is not satisfied //~^ ERROR the trait bound `S: rocket::http::uri::UriDisplay` is not satisfied
fn not_uri_display(id: i32, name: S) -> &'static str { "" } fn not_uri_display(id: i32, name: S) -> &'static str { "" }
#[post("/<id>/<name>")] #[post("/<id>/<name>")]

View File

@ -352,17 +352,10 @@ pub trait UriDisplay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result; fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
} }
impl<T: fmt::Display> UriDisplay for T {
#[inline(always)]
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl<'a> fmt::Display for &'a UriDisplay { impl<'a> fmt::Display for &'a UriDisplay {
#[inline(always)] #[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f) UriDisplay::fmt(*self, f)
} }
} }
@ -380,13 +373,51 @@ impl<'a> UriDisplay for &'a str {
} }
} }
impl<'a> UriDisplay for String { impl<'a> UriDisplay for Cow<'a, str> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", URI::percent_encode(self))
}
}
impl UriDisplay for String {
#[inline(always)] #[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", URI::percent_encode(self.as_str())) write!(f, "{}", URI::percent_encode(self.as_str()))
} }
} }
macro_rules! impl_with_display {
($($T:ty),+) => {$(
impl UriDisplay for $T {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
)+}
}
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
impl_with_display! {
i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, bool,
IpAddr, Ipv4Addr, Ipv6Addr
}
macro_rules! impl_for_ref {
($($T:ty),+) => {$(
impl<'a, T: UriDisplay + ?Sized> UriDisplay for $T {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
UriDisplay::fmt(*self, f)
}
}
)+}
}
impl_for_ref!(&'a mut T, &'a T);
/// Iterator over the segments of an absolute URI path. Skips empty segments. /// Iterator over the segments of an absolute URI path. Skips empty segments.
/// ///
/// ### Examples /// ### Examples