2017-01-21 03:31:46 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
|
2020-10-22 10:27:04 +00:00
|
|
|
use crate::rocket::Rocket;
|
2019-06-13 01:48:02 +00:00
|
|
|
use crate::request::{self, FromRequest, Request};
|
|
|
|
use crate::outcome::Outcome;
|
|
|
|
use crate::http::Status;
|
2017-01-21 03:31:46 +00:00
|
|
|
|
2017-02-03 02:00:18 +00:00
|
|
|
/// Request guard to retrieve managed state.
|
|
|
|
///
|
|
|
|
/// This type can be used as a request guard to retrieve the state Rocket is
|
|
|
|
/// managing for some type `T`. This allows for the sharing of state across any
|
|
|
|
/// number of handlers. A value for the given type must previously have been
|
2020-07-22 23:10:02 +00:00
|
|
|
/// registered to be managed by Rocket via [`Rocket::manage()`]. The type being
|
|
|
|
/// managed must be thread safe and sendable across thread boundaries. In other
|
|
|
|
/// words, it must implement [`Send`] + [`Sync`] + `'static`.
|
|
|
|
///
|
|
|
|
/// [`Rocket::manage()`]: crate::Rocket::manage()
|
2017-02-03 02:00:18 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// Imagine you have some configuration struct of the type `MyConfig` that you'd
|
|
|
|
/// like to initialize at start-up and later access it in several handlers. The
|
|
|
|
/// following example does just this:
|
|
|
|
///
|
2020-06-16 12:01:26 +00:00
|
|
|
/// ```rust,no_run
|
2018-06-28 15:55:15 +00:00
|
|
|
/// # #[macro_use] extern crate rocket;
|
2017-02-03 02:00:18 +00:00
|
|
|
/// use rocket::State;
|
|
|
|
///
|
|
|
|
/// // In a real application, this would likely be more complex.
|
2017-07-03 22:13:21 +00:00
|
|
|
/// struct MyConfig {
|
|
|
|
/// user_val: String
|
|
|
|
/// }
|
2017-02-03 02:00:18 +00:00
|
|
|
///
|
|
|
|
/// #[get("/")]
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
/// fn index(state: State<'_, MyConfig>) -> String {
|
2017-07-03 22:13:21 +00:00
|
|
|
/// format!("The config value is: {}", state.user_val)
|
2017-02-03 02:00:18 +00:00
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[get("/raw")]
|
|
|
|
/// fn raw_config_value<'r>(state: State<'r, MyConfig>) -> &'r str {
|
|
|
|
/// // use `inner()` to get a lifetime longer than `deref` gives us
|
2017-07-03 22:13:21 +00:00
|
|
|
/// state.inner().user_val.as_str()
|
2017-02-03 02:00:18 +00:00
|
|
|
/// }
|
|
|
|
///
|
2020-07-22 23:10:02 +00:00
|
|
|
/// #[launch]
|
2020-06-16 12:01:26 +00:00
|
|
|
/// fn rocket() -> rocket::Rocket {
|
2017-02-03 02:00:18 +00:00
|
|
|
/// rocket::ignite()
|
|
|
|
/// .mount("/", routes![index, raw_config_value])
|
2020-06-16 12:01:26 +00:00
|
|
|
/// .manage(MyConfig { user_val: "user input".to_string() })
|
2017-02-03 02:00:18 +00:00
|
|
|
/// }
|
|
|
|
/// ```
|
2017-07-03 22:13:21 +00:00
|
|
|
///
|
|
|
|
/// # Within Request Guards
|
|
|
|
///
|
|
|
|
/// Because `State` is itself a request guard, managed state can be retrieved
|
2021-03-15 02:57:59 +00:00
|
|
|
/// from another request guard's implementation using either
|
2021-03-26 01:33:15 +00:00
|
|
|
/// [`Request::guard()`] or [`Rocket::state()`]. In the following code example,
|
|
|
|
/// the `Item` request guard retrieves `MyConfig` from managed state:
|
2017-07-03 22:13:21 +00:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use rocket::State;
|
|
|
|
/// use rocket::request::{self, Request, FromRequest};
|
2021-03-15 02:57:59 +00:00
|
|
|
/// use rocket::outcome::IntoOutcome;
|
2017-07-03 22:13:21 +00:00
|
|
|
///
|
|
|
|
/// # struct MyConfig{ user_val: String };
|
2021-03-15 02:57:59 +00:00
|
|
|
/// struct Item<'r>(&'r str);
|
2017-07-03 22:13:21 +00:00
|
|
|
///
|
2020-01-31 09:34:15 +00:00
|
|
|
/// #[rocket::async_trait]
|
2021-03-15 02:57:59 +00:00
|
|
|
/// impl<'r> FromRequest<'r> for Item<'r> {
|
2017-07-03 22:13:21 +00:00
|
|
|
/// type Error = ();
|
|
|
|
///
|
2021-03-15 02:57:59 +00:00
|
|
|
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
|
|
|
/// // Using `State` as a request guard. Use `inner()` to get an `'r`.
|
|
|
|
/// let outcome = request.guard::<State<MyConfig>>().await
|
|
|
|
/// .map(|my_config| Item(&my_config.inner().user_val));
|
|
|
|
///
|
|
|
|
/// // Or alternatively, using `Request::managed_state()`:
|
2021-03-26 01:33:15 +00:00
|
|
|
/// let outcome = request.rocket().state::<MyConfig>()
|
2021-03-15 02:57:59 +00:00
|
|
|
/// .map(|my_config| Item(&my_config.user_val))
|
|
|
|
/// .or_forward(());
|
|
|
|
///
|
|
|
|
/// outcome
|
2017-07-03 22:13:21 +00:00
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2018-11-03 08:51:00 +00:00
|
|
|
///
|
|
|
|
/// # Testing with `State`
|
|
|
|
///
|
|
|
|
/// When unit testing your application, you may find it necessary to manually
|
|
|
|
/// construct a type of `State` to pass to your functions. To do so, use the
|
|
|
|
/// [`State::from()`] static method:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # #[macro_use] extern crate rocket;
|
|
|
|
/// use rocket::State;
|
|
|
|
///
|
|
|
|
/// struct MyManagedState(usize);
|
|
|
|
///
|
|
|
|
/// #[get("/")]
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
/// fn handler(state: State<'_, MyManagedState>) -> String {
|
2018-11-03 08:51:00 +00:00
|
|
|
/// state.0.to_string()
|
|
|
|
/// }
|
|
|
|
///
|
2020-06-14 15:57:51 +00:00
|
|
|
/// let mut rocket = rocket::ignite().manage(MyManagedState(127));
|
2020-10-22 10:27:04 +00:00
|
|
|
/// let state = State::from(&rocket).expect("managed `MyManagedState`");
|
2018-11-03 08:51:00 +00:00
|
|
|
/// assert_eq!(handler(state), "127");
|
|
|
|
/// ```
|
2017-07-03 22:39:24 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2017-01-21 03:31:46 +00:00
|
|
|
pub struct State<'r, T: Send + Sync + 'static>(&'r T);
|
|
|
|
|
|
|
|
impl<'r, T: Send + Sync + 'static> State<'r, T> {
|
2018-07-12 03:44:09 +00:00
|
|
|
/// Retrieve a borrow to the underlying value with a lifetime of `'r`.
|
2017-01-21 03:31:46 +00:00
|
|
|
///
|
2018-10-06 13:25:17 +00:00
|
|
|
/// Using this method is typically unnecessary as `State` implements
|
|
|
|
/// [`Deref`] with a [`Deref::Target`] of `T`. This means Rocket will
|
|
|
|
/// automatically coerce a `State<T>` to an `&T` as required. This method
|
|
|
|
/// should only be used when a longer lifetime is required.
|
2017-07-03 22:13:21 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use rocket::State;
|
|
|
|
///
|
|
|
|
/// struct MyConfig {
|
|
|
|
/// user_val: String
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // Use `inner()` to get a lifetime of `'r`
|
|
|
|
/// fn handler1<'r>(config: State<'r, MyConfig>) -> &'r str {
|
|
|
|
/// &config.inner().user_val
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // Use the `Deref` implementation which coerces implicitly
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
/// fn handler2(config: State<'_, MyConfig>) -> String {
|
2017-07-03 22:13:21 +00:00
|
|
|
/// config.user_val.clone()
|
|
|
|
/// }
|
|
|
|
/// ```
|
2017-03-28 10:10:18 +00:00
|
|
|
#[inline(always)]
|
2017-01-21 03:31:46 +00:00
|
|
|
pub fn inner(&self) -> &'r T {
|
|
|
|
self.0
|
|
|
|
}
|
2018-11-03 08:51:00 +00:00
|
|
|
|
|
|
|
/// Returns the managed state value in `rocket` for the type `T` if it is
|
|
|
|
/// being managed by `rocket`. Otherwise, returns `None`.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use rocket::State;
|
|
|
|
///
|
|
|
|
/// #[derive(Debug, PartialEq)]
|
|
|
|
/// struct Managed(usize);
|
|
|
|
///
|
|
|
|
/// #[derive(Debug, PartialEq)]
|
|
|
|
/// struct Unmanaged(usize);
|
|
|
|
///
|
2020-10-22 10:27:04 +00:00
|
|
|
/// let rocket = rocket::ignite().manage(Managed(7));
|
2018-11-03 08:51:00 +00:00
|
|
|
///
|
2020-10-22 10:27:04 +00:00
|
|
|
/// let state: Option<State<Managed>> = State::from(&rocket);
|
2018-11-03 08:51:00 +00:00
|
|
|
/// assert_eq!(state.map(|s| s.inner()), Some(&Managed(7)));
|
|
|
|
///
|
2020-10-22 10:27:04 +00:00
|
|
|
/// let state: Option<State<Unmanaged>> = State::from(&rocket);
|
2018-11-03 08:51:00 +00:00
|
|
|
/// assert_eq!(state, None);
|
|
|
|
/// ```
|
|
|
|
#[inline(always)]
|
2020-10-22 10:27:04 +00:00
|
|
|
pub fn from(rocket: &'r Rocket) -> Option<Self> {
|
2020-06-28 05:59:40 +00:00
|
|
|
rocket.state().map(State)
|
2018-11-03 08:51:00 +00:00
|
|
|
}
|
2017-01-21 03:31:46 +00:00
|
|
|
}
|
|
|
|
|
2020-01-31 09:34:15 +00:00
|
|
|
#[crate::async_trait]
|
2021-03-15 02:57:59 +00:00
|
|
|
impl<'r, T: Send + Sync + 'static> FromRequest<'r> for State<'r, T> {
|
2017-01-21 03:31:46 +00:00
|
|
|
type Error = ();
|
|
|
|
|
2017-03-28 10:10:18 +00:00
|
|
|
#[inline(always)]
|
2021-03-15 02:57:59 +00:00
|
|
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
2021-03-26 01:33:15 +00:00
|
|
|
match req.rocket().state::<T>() {
|
2017-03-28 10:10:18 +00:00
|
|
|
Some(state) => Outcome::Success(State(state)),
|
|
|
|
None => {
|
2021-03-24 18:59:23 +00:00
|
|
|
error_!("Attempted to retrieve unmanaged state `{}`!", std::any::type_name::<T>());
|
2017-03-28 10:10:18 +00:00
|
|
|
Outcome::Failure((Status::InternalServerError, ()))
|
2017-01-21 03:31:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-13 01:48:02 +00:00
|
|
|
impl<T: Send + Sync + 'static> Deref for State<'_, T> {
|
2017-01-21 03:31:46 +00:00
|
|
|
type Target = T;
|
|
|
|
|
2017-03-28 10:10:18 +00:00
|
|
|
#[inline(always)]
|
2017-01-21 03:31:46 +00:00
|
|
|
fn deref(&self) -> &T {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
2020-10-02 09:54:11 +00:00
|
|
|
|
|
|
|
impl<T: Send + Sync + 'static> Clone for State<'_, T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
State(self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
#[test]
|
|
|
|
fn state_is_cloneable() {
|
|
|
|
struct Token(usize);
|
|
|
|
|
2020-10-30 09:48:56 +00:00
|
|
|
let rocket = crate::custom(crate::Config::default()).manage(Token(123));
|
2020-10-02 09:54:11 +00:00
|
|
|
let state = rocket.state::<Token>().unwrap();
|
|
|
|
assert_eq!(state.0, 123);
|
|
|
|
assert_eq!(state.clone().0, 123);
|
|
|
|
}
|
|
|
|
}
|