mirror of https://github.com/rwf2/Rocket.git
Document 'FromUriParam'.
This commit is contained in:
parent
eeef8a44ce
commit
245f815657
|
@ -3,8 +3,103 @@ use std::path::{Path, PathBuf};
|
|||
use http::RawStr;
|
||||
use http::uri::UriDisplay;
|
||||
|
||||
/// Conversion trait for parameters used in `uri!` invocations.
|
||||
///
|
||||
/// This trait is invoked once per expression passed into a [`uri!`] invocation.
|
||||
/// In particular, for a route URI parameter of type `T` and a user-supplied
|
||||
/// expression of type `S`, `<T as FromUriParam<S>>::from_uri_param` is
|
||||
/// invoked. The returned value is used in place of the user's value and
|
||||
/// rendered using its [`UriDisplay`] implementation.
|
||||
///
|
||||
/// This trait allows types that differ from the route URI parameter's types to
|
||||
/// be used in their place at no cost. For instance, the following
|
||||
/// implementation, provided by Rocket, allows an `&str` to be used in a `uri!`
|
||||
/// invocation for route URI parameters declared as `String`:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// impl<'a> FromUriParam<&'a str> for String { type Target = &'a str; }
|
||||
/// ```
|
||||
///
|
||||
/// Because the `Target` type is the same as the input type, the conversion is a
|
||||
/// no-op and free of cost, allowing an `&str` to be used in place of a
|
||||
/// `String` without penalty. A similar no-op conversion exists for [`&RawStr`]:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// impl<'a, 'b> FromUriParam<&'a str> for &'b RawStr { type Target = &'a str; }
|
||||
/// ```
|
||||
///
|
||||
/// [`&RawStr`]: /rocket/http/struct.RawStr.html
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// Because Rocket provides a blanket implementation for all types, this trait
|
||||
/// typically does not need to be implemented. This trait should only be
|
||||
/// implemented when you'd like to allow a type different from the route's
|
||||
/// declared type to be used in its place in a `uri!` invocation. This is
|
||||
/// typically only warranted for owned-value types with corresponding reference
|
||||
/// types: `String` and `&str`, for instance. In this case, it's desireable to
|
||||
/// allow an `&str` to be used in place of a `String`.
|
||||
///
|
||||
/// When implementing `FromUriParam`, be aware that Rocket will use the
|
||||
/// [`UriDisplay`] implementation of `Target`, _not_ of the source type.
|
||||
/// Incorrect implementations can result in creating unsafe URIs.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// The following example implements `FromUriParam<(&str, &str)>` for a `User`
|
||||
/// type. The implementation allows an `(&str, &str)` type to be used in a
|
||||
/// `uri!` invocation where a `User` type is expected.
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// use rocket::http::RawStr;
|
||||
/// use rocket::http::uri::{UriDisplay, FromUriParam};
|
||||
///
|
||||
/// # /*
|
||||
/// #[derive(FromForm)]
|
||||
/// # */
|
||||
/// struct User<'a> {
|
||||
/// name: &'a RawStr,
|
||||
/// nickname: String,
|
||||
/// }
|
||||
///
|
||||
/// impl<'a> UriDisplay for User<'a> {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// write!(f, "name={}&nickname={}",
|
||||
/// &self.name.replace(' ', "+") as &UriDisplay,
|
||||
/// &self.nickname.replace(' ', "+") as &UriDisplay)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl<'a, 'b> FromUriParam<(&'a str, &'b str)> for User<'a> {
|
||||
/// type Target = User<'a>;
|
||||
/// fn from_uri_param((name, nickname): (&'a str, &'b str)) -> User<'a> {
|
||||
/// User { name: name.into(), nickname: nickname.to_string() }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// With these implementations, the following typechecks:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// #[post("/<name>?<query>")]
|
||||
/// fn some_route(name: &RawStr, query: User) -> T { .. }
|
||||
///
|
||||
/// uri!(some_route: name = "hey", query = ("Robert Mike", "Bob"));
|
||||
/// // => "/hey?name=Robert+Mike&nickname=Bob"
|
||||
/// ```
|
||||
///
|
||||
/// [`uri!`]: /rocket_codegen/#typed-uris-uri
|
||||
/// [`UriDisplay`]: /rocket/http/uri/trait.UriDisplay.html
|
||||
pub trait FromUriParam<T>: UriDisplay {
|
||||
/// The resulting type of this conversion.
|
||||
type Target: UriDisplay;
|
||||
|
||||
/// Converts a value of type `T` into a value of type `Self::Target`. The
|
||||
/// resulting value of type `Self::Target` will be rendered into a URI using
|
||||
/// its [`UriDisplay`](/rocket/http/uri/trait.UriDisplay.html)
|
||||
/// implementation.
|
||||
fn from_uri_param(param: T) -> Self::Target;
|
||||
}
|
||||
|
||||
|
@ -26,24 +121,28 @@ impl<'a, T: UriDisplay> FromUriParam<&'a mut T> for T {
|
|||
fn from_uri_param(param: &'a mut T) -> &'a mut T { param }
|
||||
}
|
||||
|
||||
/// A no cost conversion allowing an `&str` to be used in place of a `String`.
|
||||
impl<'a> FromUriParam<&'a str> for String {
|
||||
type Target = &'a str;
|
||||
#[inline(always)]
|
||||
fn from_uri_param(param: &'a str) -> &'a str { param }
|
||||
}
|
||||
|
||||
/// A no cost conversion allowing an `&str` to be used in place of an `&RawStr`.
|
||||
impl<'a, 'b> FromUriParam<&'a str> for &'b RawStr {
|
||||
type Target = &'a str;
|
||||
#[inline(always)]
|
||||
fn from_uri_param(param: &'a str) -> &'a str { param }
|
||||
}
|
||||
|
||||
/// A no cost conversion allowing an `&Path` to be used in place of a `PathBuf`.
|
||||
impl<'a> FromUriParam<&'a Path> for PathBuf {
|
||||
type Target = &'a Path;
|
||||
#[inline(always)]
|
||||
fn from_uri_param(param: &'a Path) -> &'a Path { param }
|
||||
}
|
||||
|
||||
/// A no cost conversion allowing an `&str` to be used in place of a `PathBuf`.
|
||||
impl<'a> FromUriParam<&'a str> for PathBuf {
|
||||
type Target = &'a Path;
|
||||
#[inline(always)]
|
||||
|
|
|
@ -7,13 +7,15 @@ use http::uri::Uri;
|
|||
|
||||
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
|
||||
define_encode_set! {
|
||||
mod priv_encode_set {
|
||||
/// This encode set is used for strings where '/' characters are known to be
|
||||
/// safe; all other special path segment characters are encoded.
|
||||
pub PATH_ENCODE_SET = [DEFAULT_ENCODE_SET] | {'%'}
|
||||
define_encode_set! { pub PATH_ENCODE_SET = [super::DEFAULT_ENCODE_SET] | {'%'} }
|
||||
}
|
||||
|
||||
/// Trait implemented by types that can be displayed as part of a URI.
|
||||
use self::priv_encode_set::PATH_ENCODE_SET;
|
||||
|
||||
/// Trait implemented by types that can be displayed as part of a URI in `uri!`.
|
||||
///
|
||||
/// Types implementing this trait can be displayed in a URI-safe manner. Unlike
|
||||
/// `Display`, the string written by a `UriDisplay` implementation must be
|
||||
|
@ -60,7 +62,7 @@ define_encode_set! {
|
|||
/// `UriDisplay`. As can be seen, the implementation will be used to display the
|
||||
/// value in a URI-safe manner.
|
||||
///
|
||||
/// [`uri!`]: /rocket_codegen/#procedural-macros
|
||||
/// [`uri!`]: /rocket_codegen/#typed-uris-uri
|
||||
///
|
||||
/// # Provided Implementations
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue