Skip to content

Commit

Permalink
impl Arbitrary for SystemTime
Browse files Browse the repository at this point in the history
  • Loading branch information
caspermeijn committed Apr 9, 2024
1 parent 803f2df commit b1d3d02
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZ
use core::ops::{Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
use core::str;
use core::time::Duration;
use std::borrow::{Cow, ToOwned};
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
use std::ffi::{CString, OsString};
use std::hash::BuildHasher;
Expand All @@ -53,6 +53,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
use std::sync::{Arc, Mutex};
use std::time::SystemTime;

/// Generate arbitrary structured values from raw, unstructured data.
///
Expand Down Expand Up @@ -1272,6 +1273,32 @@ impl<'a> Arbitrary<'a> for SocketAddr {
}
}

impl<'a> Arbitrary<'a> for SystemTime {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
// Create a SystemTime by adding or subtracting a duration from epoch.
// The result is not guaranteed to fit. Keep trying until a good SystemTime if found.
loop {
let add: bool = u.arbitrary()?;
let duration: Duration = u.arbitrary()?;
if add {
if let Some(system_time) = SystemTime::UNIX_EPOCH.checked_add(duration) {
return Ok(system_time);
}
} else if let Some(system_time) = SystemTime::UNIX_EPOCH.checked_sub(duration) {
return Ok(system_time);
}
}
}

fn size_hint(depth: usize) -> (usize, Option<usize>) {
size_hint::and_all(&[
bool::size_hint(depth),
Duration::size_hint(depth),
(0, None),
])
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -1587,6 +1614,19 @@ mod test {
);
assert_eq!((1, None), <(u8, Vec<u8>) as Arbitrary>::size_hint(0));
}

#[test]
fn size_hint_for_system_time() {
let system_time = SystemTime::size_hint(0);

// SystemTime::size_hint as minimum of bool + Duration
assert_eq!(
system_time.0,
size_hint::and(bool::size_hint(0), Duration::size_hint(0)).0
);
// SystemTime::size_hint has no maximum
assert_eq!(system_time.1, None);
}
}

/// Multiple conflicting arbitrary attributes are used on the same field:
Expand Down

0 comments on commit b1d3d02

Please sign in to comment.