1#![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#[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}