dag_pb/
lib.rs

1//! Protobuf codec.
2pub use crate::codec::{PbLink, PbNode};
3use core::convert::TryInto;
4use libipld_base::cid;
5use libipld_base::codec::Codec;
6use libipld_base::error::{BlockError, IpldError};
7use libipld_base::ipld::Ipld;
8use thiserror::Error;
9
10mod codec;
11
12/// Protobuf codec.
13#[derive(Clone, Debug, Hash, PartialEq, Eq)]
14pub struct DagPbCodec;
15
16impl Codec for DagPbCodec {
17    const VERSION: cid::Version = cid::Version::V0;
18    const CODEC: cid::Codec = cid::Codec::DagProtobuf;
19
20    type Error = ProtobufError;
21
22    fn encode(ipld: &Ipld) -> Result<Box<[u8]>, Self::Error> {
23        let pb_node: PbNode = ipld.try_into()?;
24        Ok(pb_node.into_bytes())
25    }
26
27    fn decode(data: &[u8]) -> Result<Ipld, Self::Error> {
28        Ok(PbNode::from_bytes(data)?.into())
29    }
30}
31
32/// Protobuf error.
33#[derive(Debug, Error)]
34pub enum ProtobufError {
35    #[error("{0}")]
36    Prost(#[from] prost::DecodeError),
37    #[error("{0}")]
38    Cid(#[from] cid::Error),
39    #[error("{0}")]
40    Ipld(#[from] IpldError),
41}
42
43impl From<ProtobufError> for BlockError {
44    fn from(error: ProtobufError) -> Self {
45        Self::CodecError(error.into())
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use libipld_base::cid::Cid;
53    use multihash::Sha2_256;
54    use std::collections::BTreeMap;
55
56    #[test]
57    fn test_encode_decode() {
58        let cid = Cid::new_v0(Sha2_256::digest(b"cid")).unwrap();
59        let mut pb_link = BTreeMap::<String, Ipld>::new();
60        pb_link.insert("Hash".to_string(), cid.into());
61        pb_link.insert("Name".to_string(), "block".to_string().into());
62        pb_link.insert("Tsize".to_string(), 13.into());
63
64        let links: Vec<Ipld> = vec![pb_link.into()];
65        let mut pb_node = BTreeMap::<String, Ipld>::new();
66        pb_node.insert("Data".to_string(), b"Here is some data\n".to_vec().into());
67        pb_node.insert("Links".to_string(), links.into());
68        let data: Ipld = pb_node.into();
69
70        let bytes = DagPbCodec::encode(&data).unwrap();
71        let data2 = DagPbCodec::decode(&bytes).unwrap();
72        assert_eq!(data, data2);
73    }
74}