forest/libp2p_bitswap/
store.rs1use super::*;
5use multihash_derive::MultihashDigest;
6use std::marker::PhantomData;
7use std::ops::Deref;
8
9#[auto_impl::auto_impl(&, Arc)]
11pub trait BitswapStoreRead {
12 fn contains(&self, cid: &Cid) -> anyhow::Result<bool>;
14
15 fn get(&self, cid: &Cid) -> anyhow::Result<Option<Vec<u8>>>;
17}
18
19#[auto_impl::auto_impl(&, Arc)]
21pub trait BitswapStoreReadWrite: BitswapStoreRead + Send + Sync + 'static {
22 type Hashes: MultihashDigest<64>;
24
25 fn insert(&self, block: &Block64<Self::Hashes>) -> anyhow::Result<()>;
27}
28
29pub type Block64<H> = Block<H, 64>;
30
31#[derive(Clone, Debug)]
33pub struct Block<H, const S: usize> {
34 cid: Cid,
36 data: Vec<u8>,
38 _pd: PhantomData<H>,
39}
40
41impl<H, const S: usize> Deref for Block<H, S> {
42 type Target = Cid;
43
44 fn deref(&self) -> &Self::Target {
45 &self.cid
46 }
47}
48
49impl<H, const S: usize> PartialEq for Block<H, S> {
50 fn eq(&self, other: &Self) -> bool {
51 self.cid == other.cid
52 }
53}
54
55impl<H, const S: usize> Eq for Block<H, S> {}
56
57impl<H: MultihashDigest<S>, const S: usize> Block<H, S> {
58 pub fn new(cid: Cid, data: Vec<u8>) -> anyhow::Result<Self> {
61 Self::verify_cid(&cid, &data)?;
62 Ok(Self {
63 cid,
64 data,
65 _pd: Default::default(),
66 })
67 }
68
69 pub fn cid(&self) -> &Cid {
71 &self.cid
72 }
73
74 pub fn data(&self) -> &[u8] {
76 &self.data
77 }
78
79 fn verify_cid(cid: &Cid, payload: &[u8]) -> anyhow::Result<()> {
80 let code = cid.hash().code();
81 let mh = H::try_from(code)
82 .map_err(|_| anyhow::anyhow!("unsupported multihash code {code}"))?
83 .digest(payload);
84 if mh.digest() != cid.hash().digest() {
85 anyhow::bail!("invalid multihash digest");
86 }
87 Ok(())
88 }
89}