mirror of https://github.com/rwf2/Rocket.git
parent
8f2ee138ea
commit
a474fde85b
|
@ -92,6 +92,26 @@ impl StatusClass {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`response::status`]: ../response/status/index.html
|
/// [`response::status`]: ../response/status/index.html
|
||||||
|
///
|
||||||
|
/// # (De)serialization
|
||||||
|
///
|
||||||
|
/// `Status` is both `Serialize` and `Deserialize`, represented as a `u16`. For
|
||||||
|
/// example, [`Status::Ok`] (de)serializes from/to `200`. Any integer in the
|
||||||
|
/// range `[100, 600)` is allowed to deserialize into a `Status`.`
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[cfg(feature = "serde")] mod serde {
|
||||||
|
/// # use serde_ as serde;
|
||||||
|
/// use serde::{Serialize, Deserialize};
|
||||||
|
/// use rocket::http::Status;
|
||||||
|
///
|
||||||
|
/// #[derive(Deserialize, Serialize)]
|
||||||
|
/// # #[serde(crate = "serde_")]
|
||||||
|
/// struct Foo {
|
||||||
|
/// status: Status,
|
||||||
|
/// }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Status {
|
pub struct Status {
|
||||||
/// The HTTP status code associated with this status.
|
/// The HTTP status code associated with this status.
|
||||||
|
@ -359,3 +379,50 @@ impl Ord for Status {
|
||||||
self.code.cmp(&other.code)
|
self.code.cmp(&other.code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
mod serde {
|
||||||
|
use std::fmt;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use serde_::ser::{Serialize, Serializer};
|
||||||
|
use serde_::de::{Deserialize, Deserializer, Error, Visitor, Unexpected};
|
||||||
|
|
||||||
|
impl<'a> Serialize for Status {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_u16(self.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for DeVisitor {
|
||||||
|
type Value = Status;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(formatter, "HTTP status code integer in range [100, 600)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
|
||||||
|
if v < 100 || v >= 600 {
|
||||||
|
return Err(E::invalid_value(Unexpected::Signed(v), &self));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Status::new(v as u16))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
|
||||||
|
if v < 100 || v >= 600 {
|
||||||
|
return Err(E::invalid_value(Unexpected::Unsigned(v), &self));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Status::new(v as u16))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Status {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
deserializer.deserialize_u16(DeVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use rocket::{Config, uri};
|
use rocket::{Config, uri};
|
||||||
use rocket::http::uri::{Absolute, Asterisk, Authority, Origin, Reference};
|
use rocket::http::uri::{Absolute, Asterisk, Authority, Origin, Reference};
|
||||||
use rocket::http::Method;
|
use rocket::http::{Method, Status};
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||||
struct UriContainer<'a> {
|
struct UriContainer<'a> {
|
||||||
|
@ -31,6 +31,13 @@ struct MethodContainer {
|
||||||
mpost: Method,
|
mpost: Method,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||||
|
struct StatusContainer {
|
||||||
|
a: Status,
|
||||||
|
b: Status,
|
||||||
|
c: Status,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uri_serde() {
|
fn uri_serde() {
|
||||||
figment::Jail::expect_with(|jail| {
|
figment::Jail::expect_with(|jail| {
|
||||||
|
@ -148,3 +155,52 @@ fn method_serde() {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn status_serde() {
|
||||||
|
figment::Jail::expect_with(|jail| {
|
||||||
|
jail.create_file("Rocket.toml", r#"
|
||||||
|
[default]
|
||||||
|
a = 500
|
||||||
|
b = 100
|
||||||
|
c = 404
|
||||||
|
"#)?;
|
||||||
|
|
||||||
|
let statuses: StatusContainer = Config::figment().extract()?;
|
||||||
|
assert_eq!(statuses, StatusContainer {
|
||||||
|
a: Status::InternalServerError,
|
||||||
|
b: Status::Continue,
|
||||||
|
c: Status::NotFound
|
||||||
|
});
|
||||||
|
|
||||||
|
let tmp = Figment::from(Serialized::defaults(statuses));
|
||||||
|
let statuses: StatusContainer = tmp.extract()?;
|
||||||
|
assert_eq!(statuses, StatusContainer {
|
||||||
|
a: Status::InternalServerError,
|
||||||
|
b: Status::Continue,
|
||||||
|
c: Status::NotFound
|
||||||
|
});
|
||||||
|
|
||||||
|
jail.create_file("Rocket.toml", r#"
|
||||||
|
[default]
|
||||||
|
a = 99
|
||||||
|
b = 100
|
||||||
|
c = 404
|
||||||
|
"#)?;
|
||||||
|
|
||||||
|
let statuses: Result<StatusContainer, _> = Config::figment().extract();
|
||||||
|
assert!(statuses.is_err());
|
||||||
|
|
||||||
|
jail.create_file("Rocket.toml", r#"
|
||||||
|
[default]
|
||||||
|
a = 500
|
||||||
|
b = 100
|
||||||
|
c = 600
|
||||||
|
"#)?;
|
||||||
|
|
||||||
|
let statuses: Result<StatusContainer, _> = Config::figment().extract();
|
||||||
|
assert!(statuses.is_err());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue