use super::*;
use multihash_derive::MultihashDigest;
use std::marker::PhantomData;
use std::ops::Deref;
#[auto_impl::auto_impl(&, Arc)]
pub trait BitswapStoreRead {
fn contains(&self, cid: &Cid) -> anyhow::Result<bool>;
fn get(&self, cid: &Cid) -> anyhow::Result<Option<Vec<u8>>>;
}
#[auto_impl::auto_impl(&, Arc)]
pub trait BitswapStoreReadWrite: BitswapStoreRead + Send + Sync + 'static {
type Hashes: MultihashDigest<64>;
fn insert(&self, block: &Block64<Self::Hashes>) -> anyhow::Result<()>;
}
pub type Block64<H> = Block<H, 64>;
#[derive(Clone, Debug)]
pub struct Block<H, const S: usize> {
cid: Cid,
data: Vec<u8>,
_pd: PhantomData<H>,
}
impl<H, const S: usize> Deref for Block<H, S> {
type Target = Cid;
fn deref(&self) -> &Self::Target {
&self.cid
}
}
impl<H, const S: usize> PartialEq for Block<H, S> {
fn eq(&self, other: &Self) -> bool {
self.cid == other.cid
}
}
impl<H, const S: usize> Eq for Block<H, S> {}
impl<H: MultihashDigest<S>, const S: usize> Block<H, S> {
pub fn new(cid: Cid, data: Vec<u8>) -> anyhow::Result<Self> {
Self::verify_cid(&cid, &data)?;
Ok(Self {
cid,
data,
_pd: Default::default(),
})
}
pub fn cid(&self) -> &Cid {
&self.cid
}
pub fn data(&self) -> &[u8] {
&self.data
}
fn verify_cid(cid: &Cid, payload: &[u8]) -> anyhow::Result<()> {
let code = cid.hash().code();
let mh = H::try_from(code)
.map_err(|_| anyhow::anyhow!("unsupported multihash code {code}"))?
.digest(payload);
if mh.digest() != cid.hash().digest() {
anyhow::bail!("invalid multihash digest");
}
Ok(())
}
}