use core::{ convert::{TryFrom, TryInto}, fmt::{self, Formatter}, }; use embedded_time::{self as time, duration::*, Clock as _, ConversionError, TimeError}; struct MockClock64; impl time::Clock for MockClock64 { type T = u64; const SCALING_FACTOR: time::fraction::Fraction = ::new(1, 64_000_000); fn try_now(&self) -> Result, time::clock::Error> { Ok(time::Instant::new(128_000_000)) } } #[derive(Debug)] struct MockClock32; impl time::Clock for MockClock32 { type T = u32; const SCALING_FACTOR: time::fraction::Fraction = ::new(1, 16_000_000); fn try_now(&self) -> Result, time::clock::Error> { Ok(time::Instant::new(32_000_000)) } } #[derive(Debug)] struct BadClock; impl time::Clock for BadClock { type T = u32; const SCALING_FACTOR: time::fraction::Fraction = ::new(1, 16_000_000); fn try_now(&self) -> Result, time::clock::Error> { Err(time::clock::Error::NotRunning) } } fn get_time(clock: &Clock) where u32: TryFrom, { assert_eq!( clock .try_now() .ok() .unwrap() .duration_since_epoch() .try_into(), Ok(Seconds(2_u32)) ); } #[test] fn common_types() { let then = MockClock32.try_now().unwrap(); let now = MockClock32.try_now().unwrap(); let clock64 = MockClock64 {}; let clock32 = MockClock32 {}; get_time(&clock64); get_time(&clock32); let then = then - Seconds(1_u32); assert_ne!(then, now); assert!(then < now); } #[test] fn errors() { assert_eq!(BadClock.try_now(), Err(time::clock::Error::NotRunning)); assert_eq!( TimeError::from(time::clock::Error::NotRunning), TimeError::Clock(time::clock::Error::NotRunning) ); assert_eq!( TimeError::from(ConversionError::Unspecified), TimeError::Unspecified ); assert_eq!( TimeError::from(ConversionError::ConversionFailure), TimeError::ConversionFailure ); assert_eq!( TimeError::from(ConversionError::Overflow), TimeError::Overflow ); assert_eq!( TimeError::from(ConversionError::DivByZero), TimeError::DivByZero ); assert_eq!( TimeError::from(ConversionError::NegDuration), TimeError::NegDuration ); } struct Timestamp(time::Instant) where Clock: time::Clock; impl Timestamp where Clock: time::Clock, { pub fn new(instant: time::Instant) -> Self { Timestamp(instant) } } impl fmt::Display for Timestamp where Clock: time::Clock, u64: From, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let duration = Milliseconds::::try_from(self.0.duration_since_epoch()) .map_err(|_| fmt::Error {})?; let hours = Hours::::try_from(duration).map_err(|_| fmt::Error {})?; let minutes = Minutes::::try_from(duration).map_err(|_| fmt::Error {})? % Hours(1_u32); let seconds = Seconds::::try_from(duration).map_err(|_| fmt::Error {})? % Minutes(1_u32); let milliseconds = Milliseconds::::try_from(duration).map_err(|_| fmt::Error {})? % Seconds(1_u32); f.write_fmt(format_args!( "{}:{:02}:{:02}.{:03}", hours, minutes, seconds, milliseconds )) } } #[test] fn format() { let timestamp = Timestamp::new(time::Instant::::new(321_643_392_000)); let formatted_timestamp = timestamp.to_string(); assert_eq!(formatted_timestamp, "1:23:45.678"); }