Skip to main content

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}