From c5a925c9ce62715864826195c048410092b9cac3 Mon Sep 17 00:00:00 2001 From: Bilal Mahmoud Date: Fri, 14 Apr 2023 17:44:32 +0200 Subject: [PATCH] `deer`: implement `Deserialize` for `core::time` (#2390) * feat: init cell * feat: pull in code from #1875 * feat: test cells * test: unsafe variants * test: reflection passthrough * fix: lint * Update test_impls_core_cell.rs * chore: convert from #1875 * test: duration deserialization * test: time via approx * fix: miri * feat: implement relative assert ourselves * chore: grammar c: --- libs/deer/src/impls/core.rs | 1 + libs/deer/src/impls/core/time.rs | 13 +++++++++++++ libs/deer/tests/test_impls_core_time.rs | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 libs/deer/src/impls/core/time.rs create mode 100644 libs/deer/tests/test_impls_core_time.rs diff --git a/libs/deer/src/impls/core.rs b/libs/deer/src/impls/core.rs index 4ed86a98fd7..efa4a8380ba 100644 --- a/libs/deer/src/impls/core.rs +++ b/libs/deer/src/impls/core.rs @@ -11,4 +11,5 @@ mod num; 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())]); + } +}