1use anyhow::Result;
2use libipld::{
3 cid::multihash::{self, MultihashDigest},
4 Cid,
5};
6use std::{
7 collections::HashMap,
8 rc::Rc,
9 sync::{Arc, Mutex},
10};
11
12#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub struct Block<D>
17where
18 D: AsRef<[u8]> + ?Sized,
19{
20 pub codec: u64,
21 pub data: D,
22}
23
24impl<D> Block<D>
25where
26 D: AsRef<[u8]> + ?Sized,
27{
28 pub fn new(codec: u64, data: D) -> Self
29 where
30 Self: Sized,
31 D: Sized,
32 {
33 Self { codec, data }
34 }
35
36 pub fn cid(&self, mh_code: multihash::Code) -> Cid {
37 Cid::new_v1(self.codec, mh_code.digest(self.data.as_ref()))
38 }
39
40 pub fn len(&self) -> usize {
41 self.data.as_ref().len()
42 }
43}
44
45impl<D> AsRef<[u8]> for Block<D>
46where
47 D: AsRef<[u8]>,
48{
49 fn as_ref(&self) -> &[u8] {
50 self.data.as_ref()
51 }
52}
53
54impl<'a, D> From<&'a Block<D>> for Block<&'a [u8]>
55where
56 D: AsRef<[u8]>,
57{
58 fn from(b: &'a Block<D>) -> Self {
59 Block {
60 codec: b.codec,
61 data: b.data.as_ref(),
62 }
63 }
64}
65
66pub trait Blockstore {
70 fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>>;
72
73 fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()>;
80
81 fn has(&self, k: &Cid) -> Result<bool> {
83 Ok(self.get(k)?.is_some())
84 }
85
86 fn put<D>(&self, mh_code: multihash::Code, block: &Block<D>) -> Result<Cid>
90 where
91 Self: Sized,
92 D: AsRef<[u8]>,
93 {
94 let k = block.cid(mh_code);
95 self.put_keyed(&k, block.as_ref())?;
96 Ok(k)
97 }
98
99 fn put_many<D, I>(&self, blocks: I) -> Result<()>
101 where
102 Self: Sized,
103 D: AsRef<[u8]>,
104 I: IntoIterator<Item = (multihash::Code, Block<D>)>,
105 {
106 self.put_many_keyed(blocks.into_iter().map(|(mc, b)| (b.cid(mc), b)))?;
107 Ok(())
108 }
109
110 fn put_many_keyed<D, I>(&self, blocks: I) -> Result<()>
114 where
115 Self: Sized,
116 D: AsRef<[u8]>,
117 I: IntoIterator<Item = (Cid, D)>,
118 {
119 for (c, b) in blocks {
120 self.put_keyed(&c, b.as_ref())?
121 }
122 Ok(())
123 }
124
125 fn delete_block(&self, k: &Cid) -> Result<()>;
127}
128
129impl<BS> Blockstore for &BS
130where
131 BS: Blockstore,
132{
133 fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>> {
134 (*self).get(k)
135 }
136
137 fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()> {
138 (*self).put_keyed(k, block)
139 }
140
141 fn has(&self, k: &Cid) -> Result<bool> {
142 (*self).has(k)
143 }
144
145 fn delete_block(&self, k: &Cid) -> Result<()> {
146 (*self).delete_block(k)
147 }
148
149 fn put<D>(&self, mh_code: multihash::Code, block: &Block<D>) -> Result<Cid>
150 where
151 Self: Sized,
152 D: AsRef<[u8]>,
153 {
154 (*self).put(mh_code, block)
155 }
156
157 fn put_many<D, I>(&self, blocks: I) -> Result<()>
158 where
159 Self: Sized,
160 D: AsRef<[u8]>,
161 I: IntoIterator<Item = (multihash::Code, Block<D>)>,
162 {
163 (*self).put_many(blocks)
164 }
165
166 fn put_many_keyed<D, I>(&self, blocks: I) -> Result<()>
167 where
168 Self: Sized,
169 D: AsRef<[u8]>,
170 I: IntoIterator<Item = (Cid, D)>,
171 {
172 (*self).put_many_keyed(blocks)
173 }
174}
175
176impl<BS> Blockstore for Rc<BS>
177where
178 BS: Blockstore,
179{
180 fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>> {
181 (**self).get(k)
182 }
183
184 fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()> {
185 (**self).put_keyed(k, block)
186 }
187
188 fn has(&self, k: &Cid) -> Result<bool> {
189 (**self).has(k)
190 }
191
192 fn delete_block(&self, k: &Cid) -> Result<()> {
193 (**self).delete_block(k)
194 }
195
196 fn put<D>(&self, mh_code: multihash::Code, block: &Block<D>) -> Result<Cid>
197 where
198 Self: Sized,
199 D: AsRef<[u8]>,
200 {
201 (**self).put(mh_code, block)
202 }
203
204 fn put_many<D, I>(&self, blocks: I) -> Result<()>
205 where
206 Self: Sized,
207 D: AsRef<[u8]>,
208 I: IntoIterator<Item = (multihash::Code, Block<D>)>,
209 {
210 (**self).put_many(blocks)
211 }
212
213 fn put_many_keyed<D, I>(&self, blocks: I) -> Result<()>
214 where
215 Self: Sized,
216 D: AsRef<[u8]>,
217 I: IntoIterator<Item = (Cid, D)>,
218 {
219 (**self).put_many_keyed(blocks)
220 }
221}
222
223#[derive(Debug, Default, Clone)]
224pub struct MemoryBlockstore {
225 blocks: Arc<Mutex<HashMap<Cid, Vec<u8>>>>,
226}
227
228impl MemoryBlockstore {
229 pub fn new() -> Self {
230 Self::default()
231 }
232}
233
234impl Blockstore for MemoryBlockstore {
235 fn has(&self, k: &Cid) -> Result<bool> {
236 Ok(self.blocks.lock().unwrap().contains_key(k))
237 }
238
239 fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>> {
240 Ok(self.blocks.lock().unwrap().get(k).cloned())
241 }
242
243 fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()> {
244 self.blocks.lock().unwrap().insert(*k, block.into());
245 Ok(())
246 }
247
248 fn delete_block(&self, k: &Cid) -> Result<()> {
249 self.blocks.lock().unwrap().remove(k);
250 Ok(())
251 }
252}