use crate::{diff, hash_one, repo, AHash, NoHashMap};
use std::fmt::Display;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Path {
pub raw: String,
pub is_dir: bool,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Id {
pub path: Path,
pub file_kind: Kind,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct IdRef<'a> {
pub path: &'a Path,
pub file_kind: Kind,
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct IdHash(pub AHash);
pub type IdMap<V> = NoHashMap<IdHash, V>;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct LogId {
pub hash: repo::ChangeHash,
pub path: String,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct LogIdRef<'a> {
pub hash: repo::ChangeHash,
pub path: &'a str,
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct LogIdHash(pub AHash);
pub type LogIdMap<V> = NoHashMap<LogIdHash, V>;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Kind {
Untracked,
Changed,
}
#[derive(Debug)]
pub enum Diff {
Loading,
Loaded(diff::File),
}
pub fn id_hash(id: &Id) -> IdHash {
IdHash(hash_one(id))
}
pub fn id_ref_hash(id: &IdRef<'_>) -> IdHash {
IdHash(hash_one(id))
}
pub fn id_parts_hash(path: &Path, file_kind: Kind) -> IdHash {
id_ref_hash(&IdRef { path, file_kind })
}
pub fn log_id_hash(id: &LogId) -> LogIdHash {
LogIdHash(hash_one(id))
}
pub fn log_id_ref_hash(id: &LogIdRef<'_>) -> LogIdHash {
LogIdHash(hash_one(id))
}
pub fn log_id_parts_hash(hash: repo::ChangeHash, path: &str) -> LogIdHash {
log_id_ref_hash(&LogIdRef { path, hash })
}
impl Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Path { raw: path, is_dir } = self;
write!(f, "{path}{}", if *is_dir { "/" } else { "" })
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn id_hash_eq_id_ref_hash() {
let raw = "some random path".to_string();
let path = Path { raw, is_dir: false };
let file_kind = Kind::Untracked;
assert_eq!(
id_ref_hash(&IdRef {
path: &path,
file_kind
}),
id_hash(&Id {
path: path.clone(),
file_kind
})
);
assert_eq!(
id_ref_hash(&IdRef {
path: &path,
file_kind
}),
id_parts_hash(&path, file_kind),
);
assert_ne!(
id_ref_hash(&IdRef {
path: &path,
file_kind
}),
id_hash(&Id {
path,
file_kind: Kind::Changed
})
);
}
#[test]
fn log_id_hash_eq_log_id_ref_hash() {
let path = "some change file path";
let hash = repo::hash_bytes(&[0, 1, 2]);
assert_eq!(
log_id_ref_hash(&LogIdRef { path, hash }),
log_id_hash(&LogId {
path: path.to_string(),
hash
})
);
assert_eq!(
log_id_ref_hash(&LogIdRef { path, hash }),
log_id_parts_hash(hash, path),
);
assert_ne!(
log_id_ref_hash(&LogIdRef { path, hash }),
log_id_hash(&LogId {
path: path.to_string(),
hash: repo::hash_bytes(&[255])
})
);
}
}