Skip to content

Commit b1d3d02

Browse files
committed
impl Arbitrary for SystemTime
1 parent 803f2df commit b1d3d02

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

src/lib.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZ
4343
use core::ops::{Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
4444
use core::str;
4545
use core::time::Duration;
46-
use std::borrow::{Cow, ToOwned};
46+
use std::borrow::Cow;
4747
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
4848
use std::ffi::{CString, OsString};
4949
use std::hash::BuildHasher;
@@ -53,6 +53,7 @@ use std::path::PathBuf;
5353
use std::rc::Rc;
5454
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
5555
use std::sync::{Arc, Mutex};
56+
use std::time::SystemTime;
5657

5758
/// Generate arbitrary structured values from raw, unstructured data.
5859
///
@@ -1272,6 +1273,32 @@ impl<'a> Arbitrary<'a> for SocketAddr {
12721273
}
12731274
}
12741275

1276+
impl<'a> Arbitrary<'a> for SystemTime {
1277+
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
1278+
// Create a SystemTime by adding or subtracting a duration from epoch.
1279+
// The result is not guaranteed to fit. Keep trying until a good SystemTime if found.
1280+
loop {
1281+
let add: bool = u.arbitrary()?;
1282+
let duration: Duration = u.arbitrary()?;
1283+
if add {
1284+
if let Some(system_time) = SystemTime::UNIX_EPOCH.checked_add(duration) {
1285+
return Ok(system_time);
1286+
}
1287+
} else if let Some(system_time) = SystemTime::UNIX_EPOCH.checked_sub(duration) {
1288+
return Ok(system_time);
1289+
}
1290+
}
1291+
}
1292+
1293+
fn size_hint(depth: usize) -> (usize, Option<usize>) {
1294+
size_hint::and_all(&[
1295+
bool::size_hint(depth),
1296+
Duration::size_hint(depth),
1297+
(0, None),
1298+
])
1299+
}
1300+
}
1301+
12751302
#[cfg(test)]
12761303
mod test {
12771304
use super::*;
@@ -1587,6 +1614,19 @@ mod test {
15871614
);
15881615
assert_eq!((1, None), <(u8, Vec<u8>) as Arbitrary>::size_hint(0));
15891616
}
1617+
1618+
#[test]
1619+
fn size_hint_for_system_time() {
1620+
let system_time = SystemTime::size_hint(0);
1621+
1622+
// SystemTime::size_hint as minimum of bool + Duration
1623+
assert_eq!(
1624+
system_time.0,
1625+
size_hint::and(bool::size_hint(0), Duration::size_hint(0)).0
1626+
);
1627+
// SystemTime::size_hint has no maximum
1628+
assert_eq!(system_time.1, None);
1629+
}
15901630
}
15911631

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

0 commit comments

Comments
 (0)