object_rainbow_local_map/
lib.rs1use std::sync::Arc;
2
3use imbl::{HashMap, OrdSet};
4use object_rainbow::{
5 Address, ByteNode, DiffHashes, FailFuture, Hash, ObjectHashes, Resolve, ToOutput,
6};
7
8struct EntryInner {
9 topology: Vec<Hash>,
10 data: Vec<u8>,
11}
12
13#[derive(Clone)]
14struct Entry {
15 inner: Arc<EntryInner>,
16 referenced_by: OrdSet<Hash>,
17}
18
19#[derive(Clone, Default)]
20pub struct LocalMap {
21 map: HashMap<Hash, Entry>,
22}
23
24impl LocalMap {
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn insert(
30 &mut self,
31 hash: Hash,
32 tags_hash: Hash,
33 mangle_hash: Hash,
34 topology: Vec<Hash>,
35 data: Vec<u8>,
36 ) -> object_rainbow::Result<()> {
37 if self.contains(hash) {
38 return Ok(());
39 }
40 let mut map = self.map.clone();
41 let expected = ObjectHashes {
42 diff: DiffHashes {
43 tags: tags_hash,
44 topology: topology.data_hash(),
45 mangle: mangle_hash,
46 }
47 .data_hash(),
48 data: data.data_hash(),
49 }
50 .data_hash();
51 if expected != hash {
52 return Err(object_rainbow::Error::FullHashMismatch);
53 }
54 for referenced in &topology {
55 map.get_mut(referenced)
56 .ok_or(object_rainbow::Error::HashNotFound)?
57 .referenced_by
58 .insert(hash);
59 }
60 let inner = Arc::new(EntryInner { topology, data });
61 let entry = Entry {
62 inner,
63 referenced_by: Default::default(),
64 };
65 map.insert(hash, entry);
66 self.map = map;
67 Ok(())
68 }
69
70 pub fn referenced_by(&self, hash: Hash) -> Option<impl use<> + Iterator<Item = Hash>> {
71 if let Some(entry) = self.map.get(&hash)
72 && !entry.referenced_by.is_empty()
73 {
74 Some(entry.referenced_by.clone().into_iter())
75 } else {
76 None
77 }
78 }
79
80 pub fn remove(&mut self, hash: Hash) -> Result<(), impl use<> + Iterator<Item = Hash>> {
81 if let Some(referenced_by) = self.referenced_by(hash) {
82 return Err(referenced_by);
83 }
84 let mut map = self.map.clone();
85 if let Some(Entry { inner, .. }) = self.map.remove(&hash) {
86 for referenced in &inner.topology {
87 map.get_mut(referenced)
88 .expect("unknown")
89 .referenced_by
90 .remove(&hash);
91 }
92 }
93 self.map = map;
94 Ok(())
95 }
96
97 pub fn get(&self, hash: Hash) -> Option<(&[Hash], &[u8])> {
98 self.map
99 .get(&hash)
100 .map(|entry| (&*entry.inner.topology, &*entry.inner.data))
101 }
102
103 pub fn contains(&self, hash: Hash) -> bool {
104 self.map.contains_key(&hash)
105 }
106
107 pub fn to_resolve(&self) -> Arc<dyn Resolve> {
108 Arc::new(self.clone())
109 }
110
111 fn resolve_bytes(&self, address: Address) -> object_rainbow::Result<Vec<u8>> {
112 self.get(address.hash)
113 .map(|(_, data)| data.to_owned())
114 .ok_or(object_rainbow::Error::HashNotFound)
115 }
116
117 pub fn is_empty(&self) -> bool {
118 self.map.is_empty()
119 }
120
121 pub fn len(&self) -> usize {
122 self.map.len()
123 }
124}
125
126impl Resolve for LocalMap {
127 fn resolve<'a>(
128 &'a self,
129 address: Address,
130 this: &'a Arc<dyn Resolve>,
131 ) -> FailFuture<'a, ByteNode> {
132 Box::pin(async move {
133 let data = self.resolve_bytes(address)?;
134 Ok((data, this.clone()))
135 })
136 }
137
138 fn resolve_data(&'_ self, address: Address) -> FailFuture<'_, Vec<u8>> {
139 Box::pin(async move { self.resolve_bytes(address) })
140 }
141
142 fn try_resolve_local(
143 &self,
144 address: Address,
145 this: &Arc<dyn Resolve>,
146 ) -> object_rainbow::Result<Option<ByteNode>> {
147 let data = self.resolve_bytes(address)?;
148 Ok(Some((data, this.clone())))
149 }
150}