mirror of https://github.com/rwf2/Rocket.git
Mod-export 'msg!', 'local_cache!', 'try_outcome!'.
This removes the export of each of these macros from the root, limiting their export-scope to their respective module. This is accomplished using a new internal macro, 'export!', which does some "magic" to work around rustdoc deficiencies.
This commit is contained in:
parent
41018a5112
commit
bab3b1cb5b
|
@ -0,0 +1,56 @@
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use devise::Spanned;
|
||||||
|
use devise::ext::SpanDiagnosticExt;
|
||||||
|
use devise::proc_macro2::{TokenStream, TokenTree, Punct};
|
||||||
|
use devise::syn;
|
||||||
|
|
||||||
|
use crate::syn_ext::IdentExt;
|
||||||
|
|
||||||
|
pub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {
|
||||||
|
let mac: syn::ItemMacro = syn::parse(input)?;
|
||||||
|
let macro_name = match mac.ident {
|
||||||
|
Some(ident) => ident,
|
||||||
|
None => return Err(mac.span().error("expected `macro_rules!`")),
|
||||||
|
};
|
||||||
|
|
||||||
|
// We rename the actual `macro_export` macro so we don't accidentally use it
|
||||||
|
// internally from the auto-imported crate root macro namespace.
|
||||||
|
let (attrs, def) = (mac.attrs, mac.mac);
|
||||||
|
let internal_name = macro_name.prepend("___internal_");
|
||||||
|
let mod_name = macro_name.uniqueify_with(|mut hasher| def.hash(&mut hasher));
|
||||||
|
|
||||||
|
let macro_rules_tokens = def.tokens.clone();
|
||||||
|
let decl_macro_tokens: TokenStream = def.tokens.into_iter()
|
||||||
|
.map(|t| match t {
|
||||||
|
TokenTree::Punct(p) if p.as_char() == ';' => {
|
||||||
|
let mut token = Punct::new(',', p.spacing());
|
||||||
|
token.set_span(p.span());
|
||||||
|
TokenTree::Punct(token)
|
||||||
|
},
|
||||||
|
_ => t,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod #mod_name {
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! #internal_name {
|
||||||
|
#macro_rules_tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use #internal_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#attrs)*
|
||||||
|
#[cfg(all(nightly, doc))]
|
||||||
|
pub macro #macro_name {
|
||||||
|
#decl_macro_tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(all(nightly, doc)))]
|
||||||
|
pub use #mod_name::#internal_name as #macro_name;
|
||||||
|
})
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ use crate::syn::spanned::Spanned;
|
||||||
mod uri;
|
mod uri;
|
||||||
mod uri_parsing;
|
mod uri_parsing;
|
||||||
mod test_guide;
|
mod test_guide;
|
||||||
|
mod export;
|
||||||
|
|
||||||
fn struct_maker_vec(
|
fn struct_maker_vec(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
|
@ -65,3 +66,8 @@ pub fn guide_tests_internal(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
test_guide::_macro(input)
|
test_guide::_macro(input)
|
||||||
.unwrap_or_else(|diag| diag.emit_as_item_tokens())
|
.unwrap_or_else(|diag| diag.emit_as_item_tokens())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn export_internal(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
|
export::_macro(input)
|
||||||
|
.unwrap_or_else(|diag| diag.emit_as_item_tokens())
|
||||||
|
}
|
||||||
|
|
|
@ -1062,3 +1062,10 @@ pub fn rocket_internal_uri(input: TokenStream) -> TokenStream {
|
||||||
pub fn internal_guide_tests(input: TokenStream) -> TokenStream {
|
pub fn internal_guide_tests(input: TokenStream) -> TokenStream {
|
||||||
emit!(bang::guide_tests_internal(input))
|
emit!(bang::guide_tests_internal(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[proc_macro]
|
||||||
|
/// Private Rocket internal macro: `export!`.
|
||||||
|
pub fn export(input: TokenStream) -> TokenStream {
|
||||||
|
emit!(bang::export_internal(input))
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::http::{RawStr, Status};
|
use crate::http::{RawStr, Status};
|
||||||
use crate::request::{Request, local_cache};
|
use crate::request::{Request, local_cache};
|
||||||
use crate::data::{Data, Limits};
|
use crate::data::{Data, Limits};
|
||||||
use crate::outcome::{self, IntoOutcome, Outcome::*};
|
use crate::outcome::{self, IntoOutcome, try_outcome, Outcome::*};
|
||||||
|
|
||||||
/// Type alias for the `Outcome` of [`FromData`].
|
/// Type alias for the `Outcome` of [`FromData`].
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use crate::request::Request;
|
use crate::Request;
|
||||||
|
use crate::outcome::try_outcome;
|
||||||
use crate::data::{Data, FromData, Outcome};
|
use crate::data::{Data, FromData, Outcome};
|
||||||
use crate::http::{RawStr, ext::IntoOwned};
|
use crate::http::{RawStr, ext::IntoOwned};
|
||||||
use crate::form::parser::{Parser, RawStrParser, Buffer};
|
use crate::form::parser::{Parser, RawStrParser, Buffer};
|
||||||
|
|
|
@ -88,52 +88,76 @@ use rocket_http::ContentType;
|
||||||
|
|
||||||
use crate::{data::TempFile, form::{Result, Error}};
|
use crate::{data::TempFile, form::{Result, Error}};
|
||||||
|
|
||||||
/// A helper macro for custom validation error messages.
|
crate::export! {
|
||||||
///
|
/// A helper macro for custom validation error messages.
|
||||||
/// The macro works identically to [`std::format!`] except it does not allocate
|
///
|
||||||
/// when the expression is a string literal. It returns a function (a closure)
|
/// The macro works similar to [`std::format!`]. It generates a form
|
||||||
/// that takes one parameter and evaluates to an `Err` of validation [`Error`]
|
/// [`Validation`] error message. While useful in other contexts, it is
|
||||||
/// with the formatted message. While useful in other contexts, it is designed
|
/// designed to be chained to validation results in derived `FromForm`
|
||||||
/// to be chained to validation results via `.or_else()` and `.and_then()`.
|
/// `#[field]` attributes via `.or_else()` and `.and_then()`.
|
||||||
///
|
///
|
||||||
/// Note that the macro never needs to be imported when used with a `FromForm`
|
/// [`Validation`]: crate::form::error::ErrorKind::Validation
|
||||||
/// derive; all items in [`form::validate`](crate::form::validate) are already
|
/// [`form::validate`]: crate::form::validate
|
||||||
/// in scope.
|
///
|
||||||
///
|
/// # Example
|
||||||
/// # Example
|
///
|
||||||
///
|
/// ```rust
|
||||||
/// ```rust
|
/// use rocket::form::FromForm;
|
||||||
/// use rocket::form::FromForm;
|
///
|
||||||
///
|
/// #[derive(FromForm)]
|
||||||
/// #[derive(FromForm)]
|
/// struct Person<'r> {
|
||||||
/// struct Person<'r> {
|
/// #[field(validate = len(3..).or_else(msg!("that's a short name...")))]
|
||||||
/// #[field(validate = len(3..).or_else(msg!("that's a short name...")))]
|
/// name: &'r str,
|
||||||
/// name: &'r str,
|
/// #[field(validate = contains('f').and_then(msg!("please, no `f`!")))]
|
||||||
/// #[field(validate = contains('f').and_then(msg!("please, no `f`!")))]
|
/// non_f_name: &'r str,
|
||||||
/// non_f_name: &'r str,
|
/// }
|
||||||
/// }
|
/// ```
|
||||||
/// ```
|
///
|
||||||
///
|
/// _**Note:** this macro _never_ needs to be imported when used with a
|
||||||
/// See the [top-level docs](crate::form::validate) for more examples.
|
/// `FromForm` derive; all items in [`form::validate`] are automatically in
|
||||||
#[macro_export]
|
/// scope in `FromForm` derive attributes._
|
||||||
macro_rules! msg {
|
///
|
||||||
($e:expr) => (
|
/// See the [top-level docs](crate::form::validate) for more examples.
|
||||||
|_| {
|
///
|
||||||
Err($crate::form::Errors::from($crate::form::Error::validation($e)))
|
/// # Syntax
|
||||||
as $crate::form::Result<()>
|
///
|
||||||
}
|
/// The macro has the following "signatures":
|
||||||
);
|
///
|
||||||
($($arg:tt)*) => (
|
/// ## Variant 1
|
||||||
|_| {
|
///
|
||||||
Err($crate::form::Errors::from($crate::form::Error::validation(format!($($arg)*))))
|
/// ```rust
|
||||||
as $crate::form::Result<()>
|
/// # use rocket::form;
|
||||||
}
|
/// # trait Expr {}
|
||||||
);
|
/// fn msg<'a, T, P, E: Expr>(expr: E) -> impl Fn(P) -> form::Result<'a, T>
|
||||||
|
/// # { |_| unimplemented!() }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Takes any expression and returns a function that takes any argument type
|
||||||
|
/// and evaluates to a [`form::Result`](crate::form::Result) with an `Ok` of
|
||||||
|
/// any type. The `Result` is guaranteed to be an `Err` of kind
|
||||||
|
/// [`Validation`] with `expr` as the message.
|
||||||
|
///
|
||||||
|
/// ## Variant 2
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use rocket::form;
|
||||||
|
/// # trait Format {}
|
||||||
|
/// # trait Args {}
|
||||||
|
/// fn msg<'a, T, P, A: Args>(fmt: &str, args: A) -> impl Fn(P) -> form::Result<'a, T>
|
||||||
|
/// # { |_| unimplemented!() }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Invokes the first variant as `msg!(format!(fmt, args))`.
|
||||||
|
macro_rules! msg {
|
||||||
|
($e:expr) => (|_| {
|
||||||
|
Err($crate::form::Errors::from(
|
||||||
|
$crate::form::Error::validation($e)
|
||||||
|
)) as $crate::form::Result<()>
|
||||||
|
});
|
||||||
|
($($arg:tt)*) => ($crate::form::validate::msg!(format!($($arg)*)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use msg;
|
|
||||||
|
|
||||||
/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].
|
/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the following message:
|
/// On failure, returns a validation error with the following message:
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
|
#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
|
||||||
#![doc(html_logo_url = "https://rocket.rs/images/logo-boxed.png")]
|
#![doc(html_logo_url = "https://rocket.rs/images/logo-boxed.png")]
|
||||||
#![cfg_attr(nightly, feature(doc_cfg))]
|
#![cfg_attr(nightly, feature(doc_cfg))]
|
||||||
|
#![cfg_attr(nightly, feature(decl_macro))]
|
||||||
|
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
|
|
|
@ -612,79 +612,89 @@ impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
|
crate::export! {
|
||||||
/// `Failure`.
|
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
|
||||||
///
|
/// `Failure`.
|
||||||
/// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
|
///
|
||||||
/// case of a `Forward` or `Failure` variant, the inner type is passed to
|
/// # Syntax
|
||||||
/// [`From`](std::convert::From), allowing for the conversion between specific
|
///
|
||||||
/// and more general types. The resulting forward/error is immediately returned.
|
/// The macro has the following "signature":
|
||||||
///
|
///
|
||||||
/// Because of the early return, `try_outcome!` can only be used in methods that
|
/// ```rust
|
||||||
/// return [`Outcome`].
|
/// use rocket::outcome::Outcome;
|
||||||
///
|
///
|
||||||
/// [`Outcome`]: crate::outcome::Outcome
|
/// // Returns the inner `S` if `outcome` is `Outcome::Success`. Otherwise
|
||||||
///
|
/// // returns from the caller with `Outcome<impl From<E>, impl From<F>>`.
|
||||||
/// ## Example
|
/// fn try_outcome<S, E, F>(outcome: Outcome<S, E, F>) -> S
|
||||||
///
|
/// # { unimplemented!() }
|
||||||
/// ```rust,no_run
|
/// ```
|
||||||
/// # #[macro_use] extern crate rocket;
|
///
|
||||||
/// use std::sync::atomic::{AtomicUsize, Ordering};
|
/// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
|
||||||
///
|
/// case of a `Forward` or `Failure` variant, the inner type is passed to
|
||||||
/// use rocket::State;
|
/// [`From`](std::convert::From), allowing for the conversion between
|
||||||
/// use rocket::request::{self, Request, FromRequest};
|
/// specific and more general types. The resulting forward/error is
|
||||||
/// use rocket::outcome::Outcome::*;
|
/// immediately returned. Because of the early return, `try_outcome!` can
|
||||||
///
|
/// only be used in methods that return [`Outcome`].
|
||||||
/// #[derive(Default)]
|
///
|
||||||
/// struct Atomics {
|
/// [`Outcome`]: crate::outcome::Outcome
|
||||||
/// uncached: AtomicUsize,
|
///
|
||||||
/// cached: AtomicUsize,
|
/// ## Example
|
||||||
/// }
|
///
|
||||||
///
|
/// ```rust,no_run
|
||||||
/// struct Guard1;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// struct Guard2;
|
/// use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
///
|
///
|
||||||
/// #[rocket::async_trait]
|
/// use rocket::State;
|
||||||
/// impl<'r> FromRequest<'r> for Guard1 {
|
/// use rocket::request::{self, Request, FromRequest};
|
||||||
/// type Error = ();
|
/// use rocket::outcome::{try_outcome, Outcome::*};
|
||||||
///
|
///
|
||||||
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
/// #[derive(Default)]
|
||||||
/// // Attempt to fetch the guard, passing through any error or forward.
|
/// struct Atomics {
|
||||||
/// let atomics = try_outcome!(req.guard::<State<'_, Atomics>>().await);
|
/// uncached: AtomicUsize,
|
||||||
/// atomics.uncached.fetch_add(1, Ordering::Relaxed);
|
/// cached: AtomicUsize,
|
||||||
/// req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
|
/// }
|
||||||
///
|
///
|
||||||
/// Success(Guard1)
|
/// struct Guard1;
|
||||||
/// }
|
/// struct Guard2;
|
||||||
/// }
|
///
|
||||||
///
|
/// #[rocket::async_trait]
|
||||||
/// #[rocket::async_trait]
|
/// impl<'r> FromRequest<'r> for Guard1 {
|
||||||
/// impl<'r> FromRequest<'r> for Guard2 {
|
/// type Error = ();
|
||||||
/// type Error = ();
|
///
|
||||||
///
|
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
||||||
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
/// // Attempt to fetch the guard, passing through any error or forward.
|
||||||
/// // Attempt to fetch the guard, passing through any error or forward.
|
/// let atomics = try_outcome!(req.guard::<State<'_, Atomics>>().await);
|
||||||
/// let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);
|
/// atomics.uncached.fetch_add(1, Ordering::Relaxed);
|
||||||
/// Success(Guard2)
|
/// req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
|
||||||
/// }
|
///
|
||||||
/// }
|
/// Success(Guard1)
|
||||||
/// ```
|
/// }
|
||||||
#[macro_export]
|
/// }
|
||||||
macro_rules! try_outcome {
|
///
|
||||||
($expr:expr $(,)?) => (match $expr {
|
/// #[rocket::async_trait]
|
||||||
$crate::outcome::Outcome::Success(val) => val,
|
/// impl<'r> FromRequest<'r> for Guard2 {
|
||||||
$crate::outcome::Outcome::Failure(e) => {
|
/// type Error = ();
|
||||||
return $crate::outcome::Outcome::Failure(::std::convert::From::from(e))
|
///
|
||||||
},
|
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
||||||
$crate::outcome::Outcome::Forward(f) => {
|
/// // Attempt to fetch the guard, passing through any error or forward.
|
||||||
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
|
/// let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);
|
||||||
},
|
/// Success(Guard2)
|
||||||
});
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
macro_rules! try_outcome {
|
||||||
|
($expr:expr $(,)?) => (match $expr {
|
||||||
|
$crate::outcome::Outcome::Success(val) => val,
|
||||||
|
$crate::outcome::Outcome::Failure(e) => {
|
||||||
|
return $crate::outcome::Outcome::Failure(::std::convert::From::from(e))
|
||||||
|
},
|
||||||
|
$crate::outcome::Outcome::Forward(f) => {
|
||||||
|
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use try_outcome;
|
|
||||||
|
|
||||||
impl<S, E, F> fmt::Debug for Outcome<S, E, F> {
|
impl<S, E, F> fmt::Debug for Outcome<S, E, F> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "Outcome::{}", self.formatting().1)
|
write!(f, "Outcome::{}", self.formatting().1)
|
||||||
|
|
|
@ -247,7 +247,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # #[cfg(feature = "secrets")] mod wrapper {
|
/// # #[cfg(feature = "secrets")] mod wrapper {
|
||||||
/// # use rocket::outcome::IntoOutcome;
|
/// # use rocket::outcome::{IntoOutcome, try_outcome};
|
||||||
/// # use rocket::request::{self, Outcome, FromRequest, Request};
|
/// # use rocket::request::{self, Outcome, FromRequest, Request};
|
||||||
/// # struct User { id: String, is_admin: bool }
|
/// # struct User { id: String, is_admin: bool }
|
||||||
/// # struct Database;
|
/// # struct Database;
|
||||||
|
@ -311,7 +311,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # #[cfg(feature = "secrets")] mod wrapper {
|
/// # #[cfg(feature = "secrets")] mod wrapper {
|
||||||
/// # use rocket::outcome::IntoOutcome;
|
/// # use rocket::outcome::{IntoOutcome, try_outcome};
|
||||||
/// # use rocket::request::{self, Outcome, FromRequest, Request};
|
/// # use rocket::request::{self, Outcome, FromRequest, Request};
|
||||||
/// # struct User { id: String, is_admin: bool }
|
/// # struct User { id: String, is_admin: bool }
|
||||||
/// # struct Database;
|
/// # struct Database;
|
||||||
|
|
|
@ -14,35 +14,33 @@ pub use self::from_param::{FromParam, FromSegments};
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::response::flash::FlashMessage;
|
pub use crate::response::flash::FlashMessage;
|
||||||
|
|
||||||
/// Store and immediately retrieve a value `$v` in `$request`'s local cache
|
crate::export! {
|
||||||
/// using a locally generated anonymous type to avoid type conflicts.
|
/// Store and immediately retrieve a value `$v` in `$request`'s local cache
|
||||||
///
|
/// using a locally generated anonymous type to avoid type conflicts.
|
||||||
/// # Example
|
///
|
||||||
///
|
/// # Example
|
||||||
/// ```rust
|
///
|
||||||
/// use rocket::request::local_cache;
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
/// use rocket::request::local_cache;
|
||||||
/// # let request = c.get("/");
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
///
|
/// # let request = c.get("/");
|
||||||
/// // The first store into local cache for a given type wins.
|
///
|
||||||
/// assert_eq!(request.local_cache(|| String::from("hello")), "hello");
|
/// // The first store into local cache for a given type wins.
|
||||||
///
|
/// assert_eq!(request.local_cache(|| String::from("hello")), "hello");
|
||||||
/// // The following returns the cached, previously stored value for the type.
|
///
|
||||||
/// assert_eq!(request.local_cache(|| String::from("goodbye")), "hello");
|
/// // The following returns the cached, previously stored value for the type.
|
||||||
///
|
/// assert_eq!(request.local_cache(|| String::from("goodbye")), "hello");
|
||||||
/// // This shows that we cannot cache different values of the same type; we
|
///
|
||||||
/// // _must_ use a proxy type. To avoid the need to write these manually, use
|
/// // This shows that we cannot cache different values of the same type; we
|
||||||
/// // `local_cache!`, which generates one of the fly.
|
/// // _must_ use a proxy type. To avoid the need to write these manually, use
|
||||||
/// assert_eq!(local_cache!(request, String::from("hello")), "hello");
|
/// // `local_cache!`, which generates one of the fly.
|
||||||
/// assert_eq!(local_cache!(request, String::from("goodbye")), "goodbye");
|
/// assert_eq!(local_cache!(request, String::from("hello")), "hello");
|
||||||
/// ```
|
/// assert_eq!(local_cache!(request, String::from("goodbye")), "goodbye");
|
||||||
#[macro_export]
|
/// ```
|
||||||
macro_rules! local_cache {
|
macro_rules! local_cache {
|
||||||
($request:expr, $v:expr) => ({
|
($request:expr, $v:expr $(,)?) => ({
|
||||||
struct Local<T>(T);
|
struct Local<T>(T);
|
||||||
&$request.local_cache(move || Local($v)).0
|
&$request.local_cache(move || Local($v)).0
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use local_cache;
|
|
||||||
|
|
|
@ -571,8 +571,9 @@ impl<'r> Request<'r> {
|
||||||
/// Different values of the same type _cannot_ be cached without using a
|
/// Different values of the same type _cannot_ be cached without using a
|
||||||
/// proxy, wrapper type. To avoid the need to write these manually, or for
|
/// proxy, wrapper type. To avoid the need to write these manually, or for
|
||||||
/// libraries wishing to store values of public types, use the
|
/// libraries wishing to store values of public types, use the
|
||||||
/// [`local_cache!`] macro to generate a locally anonymous wrapper type,
|
/// [`local_cache!`](crate::request::local_cache) macro to generate a
|
||||||
/// store, and retrieve the wrapped value from request-local cache.
|
/// locally anonymous wrapper type, store, and retrieve the wrapped value
|
||||||
|
/// from request-local cache.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use rocket::State;
|
use rocket::State;
|
||||||
use rocket::outcome::Outcome;
|
use rocket::outcome::{Outcome, try_outcome};
|
||||||
use rocket::request::{self, FromRequest, Request};
|
use rocket::request::{self, FromRequest, Request};
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ implementation. To do so, simply invoke `State<T>` as a guard using the
|
||||||
|
|
||||||
use rocket::State;
|
use rocket::State;
|
||||||
use rocket::request::{self, Request, FromRequest};
|
use rocket::request::{self, Request, FromRequest};
|
||||||
|
use rocket::outcome::try_outcome;
|
||||||
# use std::sync::atomic::{AtomicUsize, Ordering};
|
# use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
# struct T;
|
# struct T;
|
||||||
|
|
Loading…
Reference in New Issue