use std::time::{Duration as StdDuration, SystemTime, UNIX_EPOCH};
crate::ros_message! {
pub struct Time("builtin_interfaces/msg/Time") {
pub sec: i32,
pub nanosec: u32,
}
}
crate::ros_message! {
pub struct Duration("builtin_interfaces/msg/Duration") {
pub sec: i32,
pub nanosec: u32,
}
}
impl Time {
#[must_use]
pub fn from_nanos(nanos: i64) -> Self {
let sec = nanos.div_euclid(1_000_000_000);
let nanosec = nanos.rem_euclid(1_000_000_000) as u32;
match i32::try_from(sec) {
Ok(sec) => Self { sec, nanosec },
Err(_) if sec < 0 => Self {
sec: i32::MIN,
nanosec: 0,
},
Err(_) => Self {
sec: i32::MAX,
nanosec: 999_999_999,
},
}
}
#[must_use]
pub fn from_secs_f64(secs: f64) -> Self {
Self::from_nanos((secs * 1e9).round() as i64)
}
#[must_use]
pub fn as_nanos(&self) -> i64 {
i64::from(self.sec) * 1_000_000_000 + i64::from(self.nanosec)
}
#[must_use]
pub fn now() -> Self {
Self::from_system_time(SystemTime::now())
}
#[must_use]
pub fn from_system_time(t: SystemTime) -> Self {
match t.duration_since(UNIX_EPOCH) {
Ok(d) => Self::from_nanos(i64::try_from(d.as_nanos()).unwrap_or(i64::MAX)),
Err(e) => Self::from_nanos(-i64::try_from(e.duration().as_nanos()).unwrap_or(i64::MAX)),
}
}
}
impl Duration {
#[must_use]
pub fn from_std(d: StdDuration) -> Self {
Self {
sec: i32::try_from(d.as_secs()).unwrap_or(i32::MAX),
nanosec: d.subsec_nanos(),
}
}
#[must_use]
pub fn from_secs_f64(secs: f64) -> Self {
let t = Time::from_secs_f64(secs);
Self {
sec: t.sec,
nanosec: t.nanosec,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ros::Message;
#[test]
fn hashes_match_jazzy() {
assert_eq!(
Time::type_hash(),
"RIHS01_b106235e25a4c5ed35098aa0a61a3ee9c9b18d197f398b0e4206cea9acf9c197"
);
assert_eq!(
Duration::type_hash(),
"RIHS01_e8d009f659816f758b75334ee1a9ca5b5c0b859843261f14c7f937349599d93b"
);
}
#[test]
fn time_conversions() {
let t = Time::from_nanos(-1);
assert_eq!((t.sec, t.nanosec), (-1, 999_999_999));
assert_eq!(t.as_nanos(), -1);
let t = Time::from_secs_f64(1.5);
assert_eq!((t.sec, t.nanosec), (1, 500_000_000));
assert_eq!(Time::from_nanos(i64::MAX).sec, i32::MAX);
}
}