Skip to main content

object_rainbow_local_map/
lib.rs

1use 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}