homestar_invocation/ipld/
dag_cbor.rs

1//! Traits related to Ipld and DagCbor encoding/decoding.
2
3use crate::{consts::DAG_CBOR, Error, Unit};
4use libipld::{
5    cbor::DagCborCodec,
6    json::DagJsonCodec,
7    multihash::{Code, MultihashDigest},
8    prelude::{Codec, Decode},
9    Cid, Ipld,
10};
11use std::{
12    fs,
13    io::{Cursor, Write},
14};
15
16/// Trait for DagCbor-related encode/decode.
17pub trait DagCbor
18where
19    Self: Sized,
20    Ipld: From<Self>,
21{
22    /// Performs the conversion from an owned `Self` to Cid.
23    fn to_cid(self) -> Result<Cid, Error<Unit>> {
24        let ipld: Ipld = self.into();
25        let bytes = DagCborCodec.encode(&ipld)?;
26        let hash = Code::Sha3_256.digest(&bytes);
27        Ok(Cid::new_v1(DAG_CBOR, hash))
28    }
29
30    /// Serialize `Self` to JSON bytes.
31    fn to_dag_json(self) -> Result<Vec<u8>, Error<Unit>> {
32        let ipld: Ipld = self.into();
33        Ok(DagJsonCodec.encode(&ipld)?)
34    }
35
36    /// Serialize `Self` to JSON [String].
37    fn to_dagjson_string(self) -> Result<String, Error<Unit>> {
38        let encoded = self.to_dag_json()?;
39        // JSON spec requires UTF-8 support
40        let s = std::str::from_utf8(&encoded)?;
41        Ok(s.to_string())
42    }
43
44    /// Serialize `Self` to CBOR bytes.
45    fn to_cbor(self) -> Result<Vec<u8>, Error<Unit>> {
46        let ipld: Ipld = self.into();
47        Ok(DagCborCodec.encode(&ipld)?)
48    }
49
50    /// Deserialize `Self` from CBOR bytes.
51    fn from_cbor(data: &[u8]) -> Result<Self, Error<Unit>>
52    where
53        Self: TryFrom<Ipld>,
54    {
55        let ipld = Ipld::decode(DagCborCodec, &mut Cursor::new(data))?;
56        let from_ipld = Self::try_from(ipld).map_err(|_err| {
57            Error::<Unit>::UnexpectedIpldType(Ipld::String(
58                "Failed to convert Ipld to expected type".to_string(),
59            ))
60        })?;
61        Ok(from_ipld)
62    }
63
64    /// Serialize `Self` to a CBOR file.
65    fn to_cbor_file(self, filename: String) -> Result<(), Error<Unit>> {
66        Ok(fs::File::create(filename)?.write_all(&self.to_cbor()?)?)
67    }
68}
69
70/// Trait for DagCbor-related encode/decode for references.
71pub trait DagCborRef
72where
73    Self: Sized,
74    for<'a> Ipld: From<&'a Self>,
75{
76    /// Performs the conversion from a referenced `Self` to Cid.
77    fn to_cid(&self) -> Result<Cid, Error<Unit>> {
78        let ipld: Ipld = self.into();
79        let bytes = DagCborCodec.encode(&ipld)?;
80        let hash = Code::Sha3_256.digest(&bytes);
81        Ok(Cid::new_v1(DAG_CBOR, hash))
82    }
83}