use anyhow::Result;
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
use cid::{
multihash::{Code, MultihashDigest},
Cid,
};
use libipld_core::{
codec::{Codec, Decode, Encode},
ipld::Ipld,
serde::{from_ipld, to_ipld},
};
use serde::{de::DeserializeOwned, Serialize};
pub fn base64_encode(data: &[u8]) -> Result<String> {
Ok(BASE64_URL_SAFE_NO_PAD.encode(data))
}
pub fn base64_decode(encoded: &str) -> Result<Vec<u8>> {
BASE64_URL_SAFE_NO_PAD
.decode(encoded)
.map_err(anyhow::Error::from)
}
pub fn derive_cid<C>(block: &[u8]) -> Cid
where
C: Codec + Default,
u64: From<C>,
{
Cid::new_v1(u64::from(C::default()), Code::Blake3_256.digest(block))
}
pub fn block_encode<C, T>(encodable: &T) -> Result<(Cid, Vec<u8>)>
where
C: Codec + Default,
T: Encode<C>,
u64: From<C>,
{
let codec = C::default();
let block = codec.encode(encodable)?;
Ok((derive_cid(&block), block))
}
pub fn block_decode<C, Ipld>(block: &[u8]) -> Result<Ipld>
where
C: Codec + Default,
Ipld: Decode<C>,
{
C::default().decode::<Ipld>(block)
}
pub fn block_serialize<C, T>(any: T) -> Result<(Cid, Vec<u8>)>
where
C: Codec + Default,
T: Serialize,
Ipld: Encode<C>,
u64: From<C>,
{
block_encode(&to_ipld(any)?)
}
pub fn block_deserialize<C, T>(block: &[u8]) -> Result<T>
where
C: Codec + Default,
T: DeserializeOwned,
Ipld: Decode<C>,
{
Ok(from_ipld(block_decode(block)?)?)
}