forest/libp2p_bitswap/
store.rs1use super::*;
5use multihash_derive::MultihashDigest;
6use std::ops::Deref;
7use std::{marker::PhantomData, sync::Arc};
8
9pub trait BitswapStoreRead {
11 fn contains(&self, cid: &Cid) -> anyhow::Result<bool>;
13
14 fn get(&self, cid: &Cid) -> anyhow::Result<Option<Vec<u8>>>;
16}
17
18pub trait BitswapStoreReadWrite: BitswapStoreRead + Send + Sync + 'static {
20 type Hashes: MultihashDigest<64>;
22
23 fn insert(&self, block: &Block64<Self::Hashes>) -> anyhow::Result<()>;
25}
26
27impl<T: BitswapStoreRead> BitswapStoreRead for Arc<T> {
28 fn contains(&self, cid: &Cid) -> anyhow::Result<bool> {
29 BitswapStoreRead::contains(self.as_ref(), cid)
30 }
31
32 fn get(&self, cid: &Cid) -> anyhow::Result<Option<Vec<u8>>> {
33 BitswapStoreRead::get(self.as_ref(), cid)
34 }
35}
36
37impl<T: BitswapStoreReadWrite> BitswapStoreReadWrite for Arc<T> {
38 type Hashes = <T as BitswapStoreReadWrite>::Hashes;
39
40 fn insert(&self, block: &Block64<Self::Hashes>) -> anyhow::Result<()> {
41 BitswapStoreReadWrite::insert(self.as_ref(), block)
42 }
43}
44
45pub type Block64<H> = Block<H, 64>;
46
47#[derive(Clone, Debug)]
49pub struct Block<H, const S: usize> {
50 cid: Cid,
52 data: Vec<u8>,
54 _pd: PhantomData<H>,
55}
56
57impl<H, const S: usize> Deref for Block<H, S> {
58 type Target = Cid;
59
60 fn deref(&self) -> &Self::Target {
61 &self.cid
62 }
63}
64
65impl<H, const S: usize> PartialEq for Block<H, S> {
66 fn eq(&self, other: &Self) -> bool {
67 self.cid == other.cid
68 }
69}
70
71impl<H, const S: usize> Eq for Block<H, S> {}
72
73impl<H: MultihashDigest<S>, const S: usize> Block<H, S> {
74 pub fn new(cid: Cid, data: Vec<u8>) -> anyhow::Result<Self> {
77 Self::verify_cid(&cid, &data)?;
78 Ok(Self {
79 cid,
80 data,
81 _pd: Default::default(),
82 })
83 }
84
85 pub fn cid(&self) -> &Cid {
87 &self.cid
88 }
89
90 pub fn data(&self) -> &[u8] {
92 &self.data
93 }
94
95 fn verify_cid(cid: &Cid, payload: &[u8]) -> anyhow::Result<()> {
96 let code = cid.hash().code();
97 let mh = H::try_from(code)
98 .map_err(|_| anyhow::anyhow!("unsupported multihash code {code}"))?
99 .digest(payload);
100 if mh.digest() != cid.hash().digest() {
101 anyhow::bail!("invalid multihash digest");
102 }
103 Ok(())
104 }
105}