Implement 'De(Serialize)' for 'Method'.

This commit is contained in:
Sergio Benitez 2021-06-09 17:07:26 -07:00
parent ca655051ba
commit d2c2725689
2 changed files with 94 additions and 1 deletions

View File

@ -3,9 +3,30 @@ use std::str::FromStr;
use self::Method::*;
// TODO: Support non-standard methods, here and in codegen.
// TODO: Support non-standard methods, here and in codegen?
/// Representation of HTTP methods.
///
/// # (De)serialization
///
/// `Method` is both `Serialize` and `Deserialize`, represented as an
/// [uncased](crate::uncased) string. For example, [`Method::Get`] serializes to
/// `"GET"` and deserializes from any casing of `"GET"` including `"get"`,
/// `"GeT"`, and `"GET"`.
///
/// ```rust
/// # #[cfg(feature = "serde")] mod serde {
/// # use serde_ as serde;
/// use serde::{Serialize, Deserialize};
/// use rocket::http::Method;
///
/// #[derive(Deserialize, Serialize)]
/// # #[serde(crate = "serde_")]
/// struct Foo {
/// method: Method,
/// }
/// # }
/// ```
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Method {
/// The `GET` variant.
@ -127,3 +148,38 @@ impl fmt::Display for Method {
self.as_str().fmt(f)
}
}
#[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 Method {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
struct DeVisitor;
impl<'de> Visitor<'de> for DeVisitor {
type Value = Method;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "valid HTTP method string")
}
fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
Method::from_str(v).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
}
}
impl<'de> Deserialize<'de> for Method {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_str(DeVisitor)
}
}
}

View File

@ -4,6 +4,7 @@ use pretty_assertions::assert_eq;
use rocket::{Config, uri};
use rocket::http::uri::{Absolute, Asterisk, Authority, Origin, Reference};
use rocket::http::Method;
#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct UriContainer<'a> {
@ -23,6 +24,13 @@ struct UriContainerOwned {
reference: Reference<'static>,
}
#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct MethodContainer {
mget: Method,
mput: Method,
mpost: Method,
}
#[test]
fn uri_serde() {
figment::Jail::expect_with(|jail| {
@ -111,3 +119,32 @@ fn uri_serde_round_trip() {
reference: uri!("https://rocket.rs:8000/index.html").into(),
});
}
#[test]
fn method_serde() {
figment::Jail::expect_with(|jail| {
jail.create_file("Rocket.toml", r#"
[default]
mget = "GET"
mput = "PuT"
mpost = "post"
"#)?;
let methods: MethodContainer = Config::figment().extract()?;
assert_eq!(methods, MethodContainer {
mget: Method::Get,
mput: Method::Put,
mpost: Method::Post
});
let tmp = Figment::from(Serialized::defaults(methods));
let methods: MethodContainer = tmp.extract()?;
assert_eq!(methods, MethodContainer {
mget: Method::Get,
mput: Method::Put,
mpost: Method::Post
});
Ok(())
});
}