mos_cache/lib.rs
1//! Incremental build cache (manifest §7, §32).
2//!
3//! The dependency graph (`DepNode`) and content-addressed cache live
4//! here. The MVP 5 implementation will persist to `.mos-cache/`.
5
6#![doc(
7 html_logo_url = "https://mosaic.kjanat.dev/assets/A4.svg",
8 html_favicon_url = "https://mosaic.kjanat.dev/assets/A4.svg"
9)]
10
11use std::collections::HashMap;
12
13use mos_core::ContentHash;
14
15/// A cache entry's address. Real keys include node, style, and width
16/// hashes (manifest §32). For now the type is opaque.
17///
18/// # Examples
19///
20/// ```
21/// use mos_cache::CacheKey;
22/// use mos_core::ContentHash;
23///
24/// let key = CacheKey(ContentHash(42));
25///
26/// assert_eq!(key.0, ContentHash(42));
27/// ```
28#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
29pub struct CacheKey(pub ContentHash);
30
31/// Cache trait. Implementations: in-memory (default), on-disk (MVP 5).
32///
33/// # Examples
34///
35/// ```
36/// use mos_cache::{Cache, CacheKey, InMemoryCache};
37/// use mos_core::ContentHash;
38///
39/// let mut cache = InMemoryCache::default();
40/// let key = CacheKey(ContentHash(7));
41/// cache.put(key, vec![1, 2, 3]);
42///
43/// assert_eq!(cache.get(&key), Some(vec![1, 2, 3]));
44/// ```
45pub trait Cache {
46 /// Return a cached payload for `key`, if present.
47 ///
48 /// # Examples
49 ///
50 /// ```
51 /// use mos_cache::{Cache, CacheKey, InMemoryCache};
52 /// use mos_core::ContentHash;
53 ///
54 /// let cache = InMemoryCache::default();
55 ///
56 /// assert_eq!(cache.get(&CacheKey(ContentHash(1))), None);
57 /// ```
58 fn get(&self, key: &CacheKey) -> Option<Vec<u8>>;
59
60 /// Store `value` under `key`, replacing any previous value.
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// use mos_cache::{Cache, CacheKey, InMemoryCache};
66 /// use mos_core::ContentHash;
67 ///
68 /// let mut cache = InMemoryCache::default();
69 /// let key = CacheKey(ContentHash(1));
70 /// cache.put(key, vec![9]);
71 ///
72 /// assert_eq!(cache.get(&key), Some(vec![9]));
73 /// ```
74 fn put(&mut self, key: CacheKey, value: Vec<u8>);
75}
76
77/// Hash-map backed cache used by tests and the current MVP pipeline.
78///
79/// # Examples
80///
81/// ```
82/// use mos_cache::{Cache, CacheKey, InMemoryCache};
83/// use mos_core::ContentHash;
84///
85/// let mut cache = InMemoryCache::default();
86/// let key = CacheKey(ContentHash(5));
87/// cache.put(key, b"pdf".to_vec());
88///
89/// assert_eq!(cache.get(&key), Some(b"pdf".to_vec()));
90/// ```
91#[derive(Default, Debug)]
92pub struct InMemoryCache {
93 entries: HashMap<CacheKey, Vec<u8>>,
94}
95
96impl Cache for InMemoryCache {
97 fn get(&self, key: &CacheKey) -> Option<Vec<u8>> {
98 self.entries.get(key).cloned()
99 }
100
101 fn put(&mut self, key: CacheKey, value: Vec<u8>) {
102 self.entries.insert(key, value);
103 }
104}