use crate::{consts::DAG_CBOR, Error, Unit};
use libipld::{
cbor::DagCborCodec,
json::DagJsonCodec,
multihash::{Code, MultihashDigest},
prelude::{Codec, Decode},
Cid, Ipld,
};
use std::{
fs,
io::{Cursor, Write},
};
pub trait DagCbor
where
Self: Sized,
Ipld: From<Self>,
{
fn to_cid(self) -> Result<Cid, Error<Unit>> {
let ipld: Ipld = self.into();
let bytes = DagCborCodec.encode(&ipld)?;
let hash = Code::Sha3_256.digest(&bytes);
Ok(Cid::new_v1(DAG_CBOR, hash))
}
fn to_dag_json(self) -> Result<Vec<u8>, Error<Unit>> {
let ipld: Ipld = self.into();
Ok(DagJsonCodec.encode(&ipld)?)
}
fn to_dagjson_string(self) -> Result<String, Error<Unit>> {
let encoded = self.to_dag_json()?;
let s = std::str::from_utf8(&encoded)?;
Ok(s.to_string())
}
fn to_cbor(self) -> Result<Vec<u8>, Error<Unit>> {
let ipld: Ipld = self.into();
Ok(DagCborCodec.encode(&ipld)?)
}
fn from_cbor(data: &[u8]) -> Result<Self, Error<Unit>>
where
Self: TryFrom<Ipld>,
{
let ipld = Ipld::decode(DagCborCodec, &mut Cursor::new(data))?;
let from_ipld = Self::try_from(ipld).map_err(|_err| {
Error::<Unit>::UnexpectedIpldType(Ipld::String(
"Failed to convert Ipld to expected type".to_string(),
))
})?;
Ok(from_ipld)
}
fn to_cbor_file(self, filename: String) -> Result<(), Error<Unit>> {
Ok(fs::File::create(filename)?.write_all(&self.to_cbor()?)?)
}
}
pub trait DagCborRef
where
Self: Sized,
for<'a> Ipld: From<&'a Self>,
{
fn to_cid(&self) -> Result<Cid, Error<Unit>> {
let ipld: Ipld = self.into();
let bytes = DagCborCodec.encode(&ipld)?;
let hash = Code::Sha3_256.digest(&bytes);
Ok(Cid::new_v1(DAG_CBOR, hash))
}
}