///|
/// A filesystem identity used by incremental planning.
///
/// The timestamp is retained for Ninja-style ordering checks, while the
/// content digest prevents a same-mtime edit from being treated as up to date.
pub(all) struct FileFingerprint {
mtime_seconds : Int64
mtime_nanos : Int
size : Int
content_hash : String
} derive(Eq, Debug)
///|
pub fn FileFingerprint::from_bytes(
bytes : Bytes,
mtime_seconds~ : Int64,
mtime_nanos~ : Int,
) -> FileFingerprint {
{
mtime_seconds,
mtime_nanos,
size: bytes.length(),
content_hash: hash_bytes(bytes),
}
}
///|
pub fn FileFingerprint::from_metadata(
mtime_seconds~ : Int64,
mtime_nanos~ : Int,
size~ : Int,
content_hash~ : String,
) -> FileFingerprint {
{ mtime_seconds, mtime_nanos, size, content_hash }
}
///|
/// A 64-bit FNV-1a stream keeps the snapshot portable across all MoonBit
/// backends without depending on a host crypto library.
fn hash_bytes(bytes : Bytes) -> String {
let mut hash : UInt64 = 14695981039346656037
for byte in bytes {
hash = (hash ^ byte.to_uint64()) * 1099511628211
}
hash.to_string()
}
///|
pub fn FileFingerprint::is_newer_than(
self : FileFingerprint,
other : FileFingerprint,
) -> Bool {
if self.mtime_seconds != other.mtime_seconds {
self.mtime_seconds > other.mtime_seconds
} else {
self.mtime_nanos > other.mtime_nanos
}
}