diff --git a/libs/deer/src/impls/core.rs b/libs/deer/src/impls/core.rs index 75749330d69..3e2ab33b7d7 100644 --- a/libs/deer/src/impls/core.rs +++ b/libs/deer/src/impls/core.rs @@ -10,4 +10,5 @@ mod non_zero; mod option; mod string; mod sync; +mod time; mod unit; diff --git a/libs/deer/src/impls/core/time.rs b/libs/deer/src/impls/core/time.rs new file mode 100644 index 00000000000..6e39fbfbc7d --- /dev/null +++ b/libs/deer/src/impls/core/time.rs @@ -0,0 +1,13 @@ +use core::time::Duration; + +use error_stack::Result; + +use crate::{error::DeserializeError, Deserialize, Deserializer}; + +impl<'de> Deserialize<'de> for Duration { + type Reflection = >::Reflection; + + fn deserialize>(de: D) -> Result { + f64::deserialize(de).map(Self::from_secs_f64) + } +} diff --git a/libs/deer/tests/test_impls_core_time.rs b/libs/deer/tests/test_impls_core_time.rs new file mode 100644 index 00000000000..68294f93238 --- /dev/null +++ b/libs/deer/tests/test_impls_core_time.rs @@ -0,0 +1,19 @@ +use core::time::Duration; + +use deer_desert::{assert_tokens_with_assertion, Token}; +use proptest::prelude::*; + +#[cfg(not(miri))] +proptest! { + #[test] + fn duration_ok(value in any::()) { + let input = value.as_secs_f64(); + + assert_tokens_with_assertion(|received: Duration| { + // due to the inherent imprecise nature of floats, we cannot use `assert_eq!` + // instead we need to check if the difference between both values is <= ε + // (which is the upper bound on the relative approximation error) + assert!((received.as_secs_f64() - value.as_secs_f64()).abs() <= f64::EPSILON); + }, &[Token::Number(input.into())]); + } +}