use crate::CacheDigest;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::time::SystemTime;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FileIdentity {
pub path: PathBuf,
pub len: u64,
pub modified: SystemTime,
pub changed: Option<(i64, i64)>,
}
impl FileIdentity {
pub fn describe(path: &Path, metadata: &std::fs::Metadata) -> Option<Self> {
Some(Self {
path: path.to_path_buf(),
len: metadata.len(),
modified: metadata.modified().ok()?,
changed: change_token(metadata),
})
}
}
#[cfg(unix)]
fn change_token(metadata: &std::fs::Metadata) -> Option<(i64, i64)> {
use std::os::unix::fs::MetadataExt;
Some((metadata.ctime(), metadata.ctime_nsec()))
}
#[cfg(not(unix))]
fn change_token(_metadata: &std::fs::Metadata) -> Option<(i64, i64)> {
None
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecordedFileDigest {
pub file: FileIdentity,
pub digest: CacheDigest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FileDigestScope {
Content,
CcInput,
}
pub trait FileDigestCache: Send + Sync {
fn find(&self, scope: FileDigestScope, files: &[FileIdentity]) -> Vec<Option<CacheDigest>>;
fn record(&self, scope: FileDigestScope, entries: Vec<RecordedFileDigest>);
}
pub struct NoFileDigestCache;
impl FileDigestCache for NoFileDigestCache {
fn find(&self, _scope: FileDigestScope, files: &[FileIdentity]) -> Vec<Option<CacheDigest>> {
vec![None; files.len()]
}
fn record(&self, _scope: FileDigestScope, _entries: Vec<RecordedFileDigest>) {}
}