mirror of https://github.com/rwf2/Rocket.git
parent
7c702a5b01
commit
50c44e8fdc
|
@ -673,3 +673,39 @@ fn test_route_uri_normalization_with_prefix() {
|
||||||
uri!("/foo/bar/", world()) => "/foo/bar/world",
|
uri!("/foo/bar/", world()) => "/foo/bar/world",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_in_query() {
|
||||||
|
#[post("/?<v>")]
|
||||||
|
fn f(v: Vec<usize>) { }
|
||||||
|
|
||||||
|
#[post("/?<v>")]
|
||||||
|
fn g(v: Vec<String>) { }
|
||||||
|
|
||||||
|
#[post("/?<v>")]
|
||||||
|
fn h(v: &[u8]) { }
|
||||||
|
|
||||||
|
let bytes = vec![0u8, 1, 2];
|
||||||
|
assert_uri_eq! {
|
||||||
|
uri!(f(v = vec![1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f(v = &vec![1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f(v = &[1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f(v = [1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
|
||||||
|
uri!(f(vec![1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f(&vec![1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f(&[1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
uri!(f([1, 2, 3])) => "/?v=1&v=2&v=3",
|
||||||
|
|
||||||
|
// TODO: Introduce `RawBytes` + FromUriParam + UriDisplay impls.
|
||||||
|
// uri!(f(v = &[1, 2, 3][..])) => "/?v=1&v=2&v=3",
|
||||||
|
|
||||||
|
uri!(g(v = vec!["a", "b=c", "d"])) => "/?v=a&v=b%3Dc&v=d",
|
||||||
|
uri!(g(v = &vec!["a", "b=c", "d"])) => "/?v=a&v=b%3Dc&v=d",
|
||||||
|
uri!(g(v = ["a", "b=c", "d"])) => "/?v=a&v=b%3Dc&v=d",
|
||||||
|
uri!(g(v = &["a", "b=c", "d"])) => "/?v=a&v=b%3Dc&v=d",
|
||||||
|
|
||||||
|
uri!(h(v = bytes.as_slice())) => "/?v=%00%01%02",
|
||||||
|
uri!(h(v = &[1, 2, 3][..])) => "/?v=%01%02%03",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,15 +16,16 @@ use crate::uri::fmt::{self, Part};
|
||||||
///
|
///
|
||||||
/// In the rare case that `UriDisplay` is implemented manually, this trait, too,
|
/// In the rare case that `UriDisplay` is implemented manually, this trait, too,
|
||||||
/// must be implemented explicitly. In the majority of cases, implementation can
|
/// must be implemented explicitly. In the majority of cases, implementation can
|
||||||
/// be automated. Rocket provides [`impl_from_uri_param_identity`] to generate
|
/// be automated. Rocket provides [`impl_from_uri_param_identity!`] to generate
|
||||||
/// the _identity_ implementations automatically. For a type `T`, these are:
|
/// the _identity_ implementations automatically. For a type `T`, these are:
|
||||||
///
|
///
|
||||||
/// * `impl<P: Part> FromUriParam<P, T> for T`
|
/// * `impl<P: Part> FromUriParam<P, T> for T`
|
||||||
/// * `impl<'x, P: Part> FromUriParam<P, &'x T> for T`
|
/// * `impl<'x, P: Part> FromUriParam<P, &'x T> for T`
|
||||||
/// * `impl<'x, P: Part> FromUriParam<P, &'x mut T> for T`
|
/// * `impl<'x, P: Part> FromUriParam<P, &'x mut T> for T`
|
||||||
///
|
///
|
||||||
/// See [`impl_from_uri_param_identity!`](crate::impl_from_uri_param_identity!)
|
/// See [`impl_from_uri_param_identity!`] for usage details.
|
||||||
/// for usage details.
|
///
|
||||||
|
/// [`impl_from_uri_param_identity!`]: crate::impl_from_uri_param_identity!
|
||||||
///
|
///
|
||||||
/// # Code Generation
|
/// # Code Generation
|
||||||
///
|
///
|
||||||
|
@ -316,7 +317,31 @@ impl_from_uri_param_identity!([fmt::Path] PathBuf);
|
||||||
|
|
||||||
impl_conversion_ref! {
|
impl_conversion_ref! {
|
||||||
[fmt::Path] ('a) &'a Path => PathBuf,
|
[fmt::Path] ('a) &'a Path => PathBuf,
|
||||||
[fmt::Path] ('a) PathBuf => &'a Path
|
[fmt::Path] ('a) PathBuf => &'a Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: A specialized `RawBytes` instead of `&[u8]`. Then impl [T] => Vec<T>.
|
||||||
|
impl_from_uri_param_identity!([fmt::Query] ('a) &'a [u8]);
|
||||||
|
|
||||||
|
impl_conversion_ref! {
|
||||||
|
[fmt::Query] (T, A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>) Vec<A> => Vec<T>,
|
||||||
|
[fmt::Query] (
|
||||||
|
T,
|
||||||
|
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
|
||||||
|
const N: usize
|
||||||
|
) Vec<A> => [T; N],
|
||||||
|
|
||||||
|
[fmt::Query] (
|
||||||
|
T,
|
||||||
|
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
|
||||||
|
const N: usize
|
||||||
|
) [A; N] => Vec<T>,
|
||||||
|
|
||||||
|
[fmt::Query] (
|
||||||
|
T,
|
||||||
|
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
|
||||||
|
const N: usize
|
||||||
|
) [A; N] => [T; N],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A no cost conversion allowing an `&str` to be used in place of a `PathBuf`.
|
/// A no cost conversion allowing an `&str` to be used in place of a `PathBuf`.
|
||||||
|
|
|
@ -453,11 +453,19 @@ impl<T: UriDisplay<Query>, E> UriDisplay<Query> for Result<T, E> {
|
||||||
|
|
||||||
impl<T: UriDisplay<Query>> UriDisplay<Query> for Vec<T> {
|
impl<T: UriDisplay<Query>> UriDisplay<Query> for Vec<T> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
|
||||||
for value in self {
|
self.iter().try_for_each(|v| f.write_value(v))
|
||||||
f.write_value(value)?;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
impl<T: UriDisplay<Query>, const N: usize> UriDisplay<Query> for [T; N] {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
|
||||||
|
self.iter().try_for_each(|v| f.write_value(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UriDisplay<Query> for [u8] {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
|
||||||
|
f.write_raw(RawStr::percent_encode_bytes(self).as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue