Skip to content

Commit 2dfe020

Browse files
author
Matthias Wahl
committed
Add custom de-/serializers to StatusCode
in order to serialize it to u16 and deserialize it from most int types.
1 parent 8e6cdc9 commit 2dfe020

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

src/status_code.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use serde::de::{Error as DeError, Unexpected, Visitor};
2+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
13
use std::fmt::{self, Display};
24

35
/// HTTP response status codes.
@@ -537,6 +539,84 @@ impl StatusCode {
537539
}
538540
}
539541

542+
impl Serialize for StatusCode {
543+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
544+
where
545+
S: Serializer,
546+
{
547+
let value: u16 = *self as u16;
548+
serializer.serialize_u16(value)
549+
}
550+
}
551+
552+
struct StatusCodeU16Visitor;
553+
554+
impl<'de> Visitor<'de> for StatusCodeU16Visitor {
555+
type Value = StatusCode;
556+
557+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
558+
write!(formatter, "a u16 representing the status code")
559+
}
560+
561+
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
562+
where
563+
E: DeError,
564+
{
565+
self.visit_u16(v as u16)
566+
}
567+
568+
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
569+
where
570+
E: DeError,
571+
{
572+
self.visit_u16(v as u16)
573+
}
574+
575+
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
576+
where
577+
E: DeError,
578+
{
579+
self.visit_u16(v as u16)
580+
}
581+
582+
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
583+
where
584+
E: DeError,
585+
{
586+
use std::convert::TryFrom;
587+
match StatusCode::try_from(v) {
588+
Ok(status_code) => Ok(status_code),
589+
Err(_) => Err(DeError::invalid_value(
590+
Unexpected::Unsigned(v as u64),
591+
&self,
592+
)),
593+
}
594+
}
595+
596+
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
597+
where
598+
E: DeError,
599+
{
600+
self.visit_u16(v as u16)
601+
}
602+
603+
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
604+
where
605+
E: DeError,
606+
{
607+
self.visit_u16(v as u16)
608+
}
609+
}
610+
611+
impl<'de> Deserialize<'de> for StatusCode {
612+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
613+
where
614+
D: Deserializer<'de>,
615+
{
616+
deserializer.deserialize_any(StatusCodeU16Visitor)
617+
}
618+
}
619+
540620
impl From<StatusCode> for u16 {
541621
fn from(code: StatusCode) -> u16 {
542622
code as u16
@@ -629,3 +709,18 @@ impl Display for StatusCode {
629709
write!(f, "{}", *self as u16)
630710
}
631711
}
712+
713+
#[cfg(test)]
714+
mod test {
715+
use super::StatusCode;
716+
#[test]
717+
fn serde_as_u16() -> Result<(), serde_json::Error> {
718+
let status_code: StatusCode = serde_json::from_str("202")?;
719+
assert_eq!(StatusCode::Accepted, status_code);
720+
assert_eq!(
721+
Some(202),
722+
serde_json::to_value(&StatusCode::Accepted)?.as_u64()
723+
);
724+
Ok(())
725+
}
726+
}

0 commit comments

Comments
 (0)