use std::collections::HashMap;
use std::path::{Path, PathBuf};
use super::hash::ContentHash;
pub struct HashCache {
cache: HashMap<PathBuf, ContentHash>,
}
impl HashCache {
pub fn new() -> Self {
Self {
cache: HashMap::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
cache: HashMap::with_capacity(capacity),
}
}
pub fn get(&self, path: &Path) -> Option<&ContentHash> {
self.cache.get(path)
}
pub fn insert(&mut self, path: PathBuf, hash: ContentHash) {
self.cache.insert(path, hash);
}
pub fn remove(&mut self, path: &Path) -> Option<ContentHash> {
self.cache.remove(path)
}
pub fn contains(&self, path: &Path) -> bool {
self.cache.contains_key(path)
}
pub fn clear(&mut self) {
self.cache.clear();
}
pub fn len(&self) -> usize {
self.cache.len()
}
pub fn is_empty(&self) -> bool {
self.cache.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&PathBuf, &ContentHash)> {
self.cache.iter()
}
}
impl Default for HashCache {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::incremental::FileHasher;
#[test]
fn test_new_cache_is_empty() {
let cache = HashCache::new();
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
}
#[test]
fn test_with_capacity() {
let cache = HashCache::with_capacity(100);
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
}
#[test]
fn test_insert_and_get() {
let mut cache = HashCache::new();
let path = PathBuf::from("src/main.rs");
let hash = FileHasher::hash_bytes(b"test content");
cache.insert(path.clone(), hash);
assert_eq!(cache.len(), 1);
assert_eq!(cache.get(&path), Some(&hash));
}
#[test]
fn test_get_nonexistent() {
let cache = HashCache::new();
let path = PathBuf::from("nonexistent.rs");
assert_eq!(cache.get(&path), None);
}
#[test]
fn test_insert_overwrites() {
let mut cache = HashCache::new();
let path = PathBuf::from("src/main.rs");
let hash1 = FileHasher::hash_bytes(b"content 1");
let hash2 = FileHasher::hash_bytes(b"content 2");
cache.insert(path.clone(), hash1);
cache.insert(path.clone(), hash2);
assert_eq!(cache.len(), 1);
assert_eq!(cache.get(&path), Some(&hash2));
}
#[test]
fn test_remove() {
let mut cache = HashCache::new();
let path = PathBuf::from("src/main.rs");
let hash = FileHasher::hash_bytes(b"test content");
cache.insert(path.clone(), hash);
let removed = cache.remove(&path);
assert_eq!(removed, Some(hash));
assert_eq!(cache.len(), 0);
assert_eq!(cache.get(&path), None);
}
#[test]
fn test_remove_nonexistent() {
let mut cache = HashCache::new();
let path = PathBuf::from("nonexistent.rs");
let removed = cache.remove(&path);
assert_eq!(removed, None);
}
#[test]
fn test_contains() {
let mut cache = HashCache::new();
let path = PathBuf::from("src/main.rs");
let hash = FileHasher::hash_bytes(b"test content");
assert!(!cache.contains(&path));
cache.insert(path.clone(), hash);
assert!(cache.contains(&path));
}
#[test]
fn test_clear() {
let mut cache = HashCache::new();
let path1 = PathBuf::from("src/main.rs");
let path2 = PathBuf::from("src/lib.rs");
let hash1 = FileHasher::hash_bytes(b"content 1");
let hash2 = FileHasher::hash_bytes(b"content 2");
cache.insert(path1, hash1);
cache.insert(path2, hash2);
assert_eq!(cache.len(), 2);
cache.clear();
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
}
#[test]
fn test_multiple_paths() {
let mut cache = HashCache::new();
let paths_and_hashes: Vec<(PathBuf, ContentHash)> = vec![
(
PathBuf::from("src/main.rs"),
FileHasher::hash_bytes(b"main"),
),
(PathBuf::from("src/lib.rs"), FileHasher::hash_bytes(b"lib")),
(
PathBuf::from("tests/test.rs"),
FileHasher::hash_bytes(b"test"),
),
];
for (path, hash) in &paths_and_hashes {
cache.insert(path.clone(), *hash);
}
assert_eq!(cache.len(), 3);
for (path, hash) in &paths_and_hashes {
assert_eq!(cache.get(path), Some(hash));
}
}
#[test]
fn test_iter() {
let mut cache = HashCache::new();
let path1 = PathBuf::from("src/main.rs");
let path2 = PathBuf::from("src/lib.rs");
let hash1 = FileHasher::hash_bytes(b"main");
let hash2 = FileHasher::hash_bytes(b"lib");
cache.insert(path1.clone(), hash1);
cache.insert(path2.clone(), hash2);
let entries: Vec<_> = cache.iter().collect();
assert_eq!(entries.len(), 2);
}
#[test]
fn test_default() {
let cache = HashCache::default();
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
}
}