libipld_pb/
lib.rs

1//! Protobuf codec.
2#![deny(missing_docs)]
3
4use crate::codec::PbNodeRef;
5pub use crate::codec::{PbLink, PbNode};
6
7use core::convert::{TryFrom, TryInto};
8use libipld_core::cid::Cid;
9use libipld_core::codec::{Codec, Decode, Encode, References};
10use libipld_core::error::{Result, UnsupportedCodec};
11use libipld_core::ipld::Ipld;
12use std::io::{Read, Seek, Write};
13
14mod codec;
15
16/// Protobuf codec.
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
18pub struct DagPbCodec;
19
20impl Codec for DagPbCodec {}
21
22impl From<DagPbCodec> for u64 {
23    fn from(_: DagPbCodec) -> Self {
24        0x70
25    }
26}
27
28impl TryFrom<u64> for DagPbCodec {
29    type Error = UnsupportedCodec;
30
31    fn try_from(_: u64) -> core::result::Result<Self, Self::Error> {
32        Ok(Self)
33    }
34}
35
36impl Encode<DagPbCodec> for Ipld {
37    fn encode<W: Write>(&self, _: DagPbCodec, w: &mut W) -> Result<()> {
38        let pb_node: PbNodeRef = self.try_into()?;
39        let bytes = pb_node.into_bytes();
40        w.write_all(&bytes)?;
41        Ok(())
42    }
43}
44
45impl Decode<DagPbCodec> for Ipld {
46    fn decode<R: Read + Seek>(_: DagPbCodec, r: &mut R) -> Result<Self> {
47        let mut bytes = Vec::new();
48        r.read_to_end(&mut bytes)?;
49        let node = PbNode::from_bytes(bytes.into())?;
50        Ok(node.into())
51    }
52}
53
54impl References<DagPbCodec> for Ipld {
55    fn references<R: Read + Seek, E: Extend<Cid>>(
56        _: DagPbCodec,
57        r: &mut R,
58        set: &mut E,
59    ) -> Result<()> {
60        let mut bytes = Vec::new();
61        r.read_to_end(&mut bytes)?;
62        PbNode::links(bytes.into(), set)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use libipld_core::cid::Cid;
70    use libipld_core::multihash::{Code, MultihashDigest};
71    use std::collections::BTreeMap;
72
73    #[test]
74    fn test_encode_decode() {
75        let digest = Code::Blake3_256.digest(&b"cid"[..]);
76        let cid = Cid::new_v1(0x55, digest);
77        let mut pb_link = BTreeMap::<String, Ipld>::new();
78        pb_link.insert("Hash".to_string(), cid.into());
79        pb_link.insert("Name".to_string(), "block".to_string().into());
80        pb_link.insert("Tsize".to_string(), 13.into());
81
82        let links: Vec<Ipld> = vec![pb_link.into()];
83        let mut pb_node = BTreeMap::<String, Ipld>::new();
84        pb_node.insert("Data".to_string(), b"Here is some data\n".to_vec().into());
85        pb_node.insert("Links".to_string(), links.into());
86        let data: Ipld = pb_node.into();
87
88        let bytes = DagPbCodec.encode(&data).unwrap();
89        let data2 = DagPbCodec.decode(&bytes).unwrap();
90        assert_eq!(data, data2);
91    }
92}