pub mod car_stream;
pub mod car_util;
use anyhow::Context as _;
use cid::{
multihash::{Code, MultihashDigest},
Cid,
};
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::CborStore;
use fvm_ipld_encoding::{to_vec, DAG_CBOR};
use serde::ser::Serialize;
pub trait BlockstoreExt: Blockstore {
fn bulk_put<'a, S, V>(&self, values: V, code: Code) -> anyhow::Result<Vec<Cid>>
where
Self: Sized,
S: Serialize + 'a,
V: IntoIterator<Item = &'a S>,
{
let keyed_objects = values
.into_iter()
.map(|value| {
let bytes = to_vec(value)?;
let cid = Cid::new_v1(DAG_CBOR, code.digest(&bytes));
Ok((cid, bytes))
})
.collect::<anyhow::Result<Vec<_>>>()?;
let cids = keyed_objects
.iter()
.map(|(cid, _)| cid.to_owned())
.collect();
self.put_many_keyed(keyed_objects)?;
Ok(cids)
}
fn get_required(&self, cid: &Cid) -> anyhow::Result<Vec<u8>> {
self.get(cid)?
.with_context(|| format!("Entry not found in block store: cid={cid}"))
}
}
impl<T: fvm_ipld_blockstore::Blockstore> BlockstoreExt for T {}
pub trait CborStoreExt: CborStore {
fn default_code() -> cid::multihash::Code {
cid::multihash::Code::Blake2b256
}
fn put_cbor_default<S: serde::ser::Serialize>(&self, obj: &S) -> anyhow::Result<Cid> {
self.put_cbor(obj, Self::default_code())
}
fn get_cbor_required<T>(&self, cid: &Cid) -> anyhow::Result<T>
where
T: serde::de::DeserializeOwned,
{
self.get_cbor(cid)?.with_context(|| {
format!(
"Entry not found in cbor store: cid={cid}, type={}",
std::any::type_name::<T>()
)
})
}
}
impl<T: CborStore> CborStoreExt for T {}