1use crate::{Digest, Meta, Store, StoreError};
22use somatize_core::{Keeper, KeeperError, Kept, Key, Value};
23
24pub struct Cache<'a> {
26 store: &'a dyn Store,
27}
28
29impl<'a> Cache<'a> {
30 pub fn over(store: &'a dyn Store) -> Self {
32 Self { store }
33 }
34}
35
36impl Keeper for Cache<'_> {
37 fn key_of(&self, value: &Value) -> Option<Key> {
38 match value.travels() {
39 true => bytes_of(value).ok().map(|bytes| key(Digest::of(&bytes))),
40 false => None,
41 }
42 }
43
44 fn combine(&self, parts: &[&str]) -> Key {
45 let mut recipe = Vec::new();
46 for part in parts {
47 recipe.extend_from_slice(&(part.len() as u64).to_le_bytes());
49 recipe.extend_from_slice(part.as_bytes());
50 }
51 key(Digest::of(&recipe))
52 }
53
54 fn present(&self, keys: &[&Key]) -> Result<Vec<bool>, KeeperError> {
59 let names: Vec<String> = keys.iter().map(|key| name_of(key)).collect();
60 let asked: Vec<&str> = names.iter().map(String::as_str).collect();
61 Ok(self
62 .store
63 .resolve_many(&asked)
64 .map_err(failed)?
65 .into_iter()
66 .map(|bound| bound.is_some())
67 .collect())
68 }
69
70 fn recall(&self, keys: &[&Key]) -> Result<Vec<Option<Kept>>, KeeperError> {
71 let names: Vec<String> = keys.iter().map(|key| name_of(key)).collect();
72 let asked: Vec<&str> = names.iter().map(String::as_str).collect();
73 let bound = self.store.resolve_many(&asked).map_err(failed)?;
74
75 let wanted: Vec<&Digest> = bound.iter().flatten().map(|bound| &bound.digest).collect();
79 let mut bytes = self.store.get_many(&wanted).map_err(failed)?.into_iter();
80
81 bound
82 .into_iter()
83 .map(|bound| {
84 let Some(bound) = bound else { return Ok(None) };
85 let Some(Some(bytes)) = bytes.next() else {
89 return Ok(None);
90 };
91 Ok(Some(Kept {
92 value: value_of(&bytes)?,
93 meta: bound.meta,
94 }))
95 })
96 .collect()
97 }
98
99 fn keep(&self, key: &Key, value: &Value, meta: &[(&str, &str)]) -> Result<(), KeeperError> {
100 let bytes = bytes_of(value)?;
101 let digest = self.store.put(&bytes).map_err(failed)?;
102 let meta: Meta = meta
103 .iter()
104 .map(|(what, said)| (what.to_string(), said.to_string()))
105 .collect();
106 self.store
107 .bind(&name_of(key), &digest, meta)
108 .map_err(failed)
109 }
110}
111
112fn key(digest: Digest) -> Key {
114 Key::new(digest.to_string())
115}
116
117pub fn name_of(key: &Key) -> String {
123 format!("value:{key}")
124}
125
126pub fn bytes_of(value: &Value) -> Result<Vec<u8>, KeeperError> {
128 if !value.travels() {
129 return Err(KeeperError::new(
130 "an opaque value cannot be kept: what it carries only exists in this process, \
131 and a store outlives it. Whoever knows how to turn it into bytes has to do so \
132 before it gets here",
133 ));
134 }
135 rmp_serde::to_vec(value)
136 .map_err(|e| KeeperError::new(format!("that value could not be written down: {e}")))
137}
138
139pub fn value_of(bytes: &[u8]) -> Result<Value, KeeperError> {
142 let mut rest = bytes;
143 let value: Value = rmp_serde::from_read(&mut rest)
144 .map_err(|e| KeeperError::new(format!("what is kept there cannot be read: {e}")))?;
145 match rest.len() {
146 0 => Ok(value),
147 left => Err(KeeperError::new(format!(
148 "what is kept there has {left} bytes too many at the end"
149 ))),
150 }
151}
152
153fn failed(e: StoreError) -> KeeperError {
154 KeeperError::new(e.to_string())
155}