diff --git a/serde_with/src/de/impls.rs b/serde_with/src/de/impls.rs index 78357fd6..ed25d9d3 100644 --- a/serde_with/src/de/impls.rs +++ b/serde_with/src/de/impls.rs @@ -165,6 +165,24 @@ where } } +impl<'de, T, U> DeserializeAs<'de, Bound> for Bound +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + Ok( + match Bound::>::deserialize(deserializer)? { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(v) => Bound::Included(v.into_inner()), + Bound::Excluded(v) => Bound::Excluded(v.into_inner()), + }, + ) + } +} + #[cfg(feature = "alloc")] impl<'de, T, U> DeserializeAs<'de, Rc> for Rc where diff --git a/serde_with/src/lib.rs b/serde_with/src/lib.rs index dd1b2718..05f69132 100644 --- a/serde_with/src/lib.rs +++ b/serde_with/src/lib.rs @@ -403,6 +403,7 @@ pub(crate) mod prelude { fmt::{self, Display}, hash::{BuildHasher, Hash}, marker::PhantomData, + ops::Bound, option::Option, result::Result, str::FromStr, diff --git a/serde_with/src/ser/impls.rs b/serde_with/src/ser/impls.rs index c6c37dd1..dae073ed 100644 --- a/serde_with/src/ser/impls.rs +++ b/serde_with/src/ser/impls.rs @@ -130,6 +130,24 @@ where } } +impl SerializeAs> for Bound +where + U: SerializeAs, + T: Sized, +{ + fn serialize_as(source: &Bound, serializer: S) -> Result + where + S: Serializer, + { + match source { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(ref v) => Bound::Included(SerializeAsWrap::::new(v)), + Bound::Excluded(ref v) => Bound::Excluded(SerializeAsWrap::::new(v)), + } + .serialize(serializer) + } +} + #[cfg(feature = "alloc")] impl SerializeAs> for Rc where diff --git a/serde_with/tests/serde_as/lib.rs b/serde_with/tests/serde_as/lib.rs index 23e1ba85..953b5abd 100644 --- a/serde_with/tests/serde_as/lib.rs +++ b/serde_with/tests/serde_as/lib.rs @@ -29,6 +29,7 @@ use alloc::{ sync::{Arc, Weak as ArcWeak}, }; use core::cell::{Cell, RefCell}; +use core::ops::Bound; use expect_test::expect; use serde::{Deserialize, Serialize}; use serde_with::{ @@ -136,6 +137,41 @@ fn test_option() { ); } +#[test] +fn test_bound() { + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct S(#[serde_as(as = "Bound")] Bound); + + is_equal(S(Bound::Unbounded), expect![[r#""Unbounded""#]]); + is_equal( + S(Bound::Included(42)), + expect![[r#" + { + "Included": "42" + }"#]], + ); + is_equal( + S(Bound::Excluded(42)), + expect![[r#" + { + "Excluded": "42" + }"#]], + ); + check_error_deserialization::(r#"{}"#, expect![[r#"expected value at line 1 column 2"#]]); + + #[serde_as] + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct Struct { + #[serde_as(as = "Bound")] + value: Bound, + } + check_error_deserialization::( + r#"{}"#, + expect![[r#"missing field `value` at line 1 column 2"#]], + ); +} + #[test] fn test_result() { #[serde_as]