use serde::{Deserialize, Serialize}; use std::path::Path; /// A timestamp used to measure changes to a file. /// /// On Unix, this uses `ctime` as a conservative approach. `ctime` should detect all /// modifications, including some that we don't care about, like hardlink modifications. /// On other platforms, it uses `mtime`. /// /// See: /// See: #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] pub struct Timestamp(std::time::SystemTime); impl Timestamp { /// Return the [`Timestamp`] for the given path. pub fn from_path(path: impl AsRef) -> std::io::Result { let metadata = fs_err::metadata(path.as_ref())?; Ok(Self::from_metadata(&metadata)) } /// Return the [`Timestamp`] for the given metadata. pub fn from_metadata(metadata: &std::fs::Metadata) -> Self { #[cfg(unix)] { use std::os::unix::fs::MetadataExt; let ctime = u64::try_from(metadata.ctime()).expect("ctime to be representable as u64"); let ctime_nsec = u32::try_from(metadata.ctime_nsec()) .expect("ctime_nsec to be representable as u32"); let duration = std::time::Duration::new(ctime, ctime_nsec); Self(std::time::UNIX_EPOCH + duration) } #[cfg(not(unix))] { let modified = metadata.modified().expect("modified time to be available"); Self(modified) } } /// Return the current [`Timestamp`]. pub fn now() -> Self { Self(std::time::SystemTime::now()) } }