|
| 1 | +use serde::de::{Error as DeError, Unexpected, Visitor}; |
| 2 | +use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
1 | 3 | use std::fmt::{self, Display};
|
2 | 4 |
|
3 | 5 | /// HTTP response status codes.
|
@@ -537,6 +539,84 @@ impl StatusCode {
|
537 | 539 | }
|
538 | 540 | }
|
539 | 541 |
|
| 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 | + |
540 | 620 | impl From<StatusCode> for u16 {
|
541 | 621 | fn from(code: StatusCode) -> u16 {
|
542 | 622 | code as u16
|
@@ -629,3 +709,18 @@ impl Display for StatusCode {
|
629 | 709 | write!(f, "{}", *self as u16)
|
630 | 710 | }
|
631 | 711 | }
|
| 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