1use crate::{
2 codec::*,
3 Ipld,
4 References,
5};
6use alloc::string::{
7 String,
8 ToString,
9};
10use bytecursor::ByteCursor;
11use core::convert::TryFrom;
12use sp_cid::Cid;
13use sp_multihash::{
14 Code,
15 MultihashDigest,
16};
17
18mod codec;
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
21pub struct DagJsonCodec;
22
23impl Codec for DagJsonCodec {}
24
25impl From<DagJsonCodec> for u64 {
26 fn from(_: DagJsonCodec) -> Self { 0x0129 }
27}
28
29impl TryFrom<u64> for DagJsonCodec {
30 type Error = UnsupportedCodec;
31
32 fn try_from(_: u64) -> core::result::Result<Self, Self::Error> { Ok(Self) }
33}
34
35impl Encode<DagJsonCodec> for Ipld {
36 fn encode(&self, _: DagJsonCodec, w: &mut ByteCursor) -> Result<(), String> {
37 codec::encode(self, w).map_err(|x| x.to_string())
38 }
39}
40
41impl Decode<DagJsonCodec> for Ipld {
42 fn decode(_: DagJsonCodec, r: &mut ByteCursor) -> Result<Self, String> {
43 codec::decode(r).map_err(|e| e.to_string())
44 }
45}
46
47impl References<DagJsonCodec> for Ipld {
48 fn references<E: Extend<Cid>>(
49 c: DagJsonCodec,
50 r: &mut ByteCursor,
51 set: &mut E,
52 ) -> Result<(), String> {
53 Ipld::decode(c, r)?.references(set);
54 Ok(())
55 }
56}
57
58pub fn cid(dag: &Ipld) -> Cid {
64 Cid::new_v1(
65 0x0129,
66 Code::Blake2b256
67 .digest(DagJsonCodec.encode(dag).unwrap().into_inner().as_ref()),
68 )
69}
70
71pub fn from_dag_json_string(s: String) -> Result<Ipld, String> {
77 let mut r = ByteCursor::new(s.into_bytes());
78 codec::decode(&mut r).map_err(|e| e.to_string())
79}
80
81pub fn to_dag_json_string(ipld: Ipld) -> Result<String, String> {
86 let mut w = ByteCursor::new(vec![]);
87 codec::encode(&ipld, &mut w).map_err(|e| e.to_string())?;
88 Ok(String::from(String::from_utf8_lossy(&w.into_inner())))
89}
90
91#[cfg(test)]
92pub mod tests {
93 use super::*;
94 use crate::ipld::*;
95 use bytecursor::ByteCursor;
96 use quickcheck::{
97 quickcheck,
98 Arbitrary,
99 Gen,
100 };
101
102 use alloc::collections::btree_map::BTreeMap;
103
104 fn encode_decode_id<
105 T: Encode<DagJsonCodec> + Decode<DagJsonCodec> + PartialEq<T> + Clone,
106 >(
107 value: T,
108 ) -> bool {
109 let mut bc = ByteCursor::new(Vec::new());
110 match Encode::encode(&value, DagJsonCodec, &mut bc) {
111 Ok(()) => {
112 bc.set_position(0);
113 match Decode::decode(DagJsonCodec, &mut bc) {
114 Ok(new_value) => return value == new_value,
115 Err(e) => println!("Error occurred during decoding: {}", e),
116 }
117 }
118 Err(e) => println!("Error occurred during encoding: {}", e),
119 }
120 false
121 }
122
123 #[quickcheck]
124 pub fn edid_null() -> bool { encode_decode_id(Ipld::Null) }
125
126 #[quickcheck]
127 pub fn edid_bool(x: bool) -> bool { encode_decode_id(Ipld::Bool(x)) }
128
129 #[quickcheck]
130 pub fn edid_integer(x: i64) -> bool {
131 encode_decode_id(Ipld::Integer(x as i128))
132 }
133
134 #[quickcheck]
135 pub fn edid_bytes(x: Vec<u8>) -> bool { encode_decode_id(Ipld::Bytes(x)) }
136
137 #[quickcheck]
138 pub fn edid_string(x: String) -> bool { encode_decode_id(Ipld::String(x)) }
139
140 #[quickcheck]
142 pub fn edid_list(x: Vec<Ipld>) -> bool { encode_decode_id(Ipld::List(x)) }
143
144 #[quickcheck]
145 pub fn edid_string_map(x: BTreeMap<String, Ipld>) -> bool {
146 encode_decode_id(Ipld::StringMap(x))
147 }
148
149 #[derive(Debug, Clone)]
150 pub struct ACid(pub Cid);
151
152 impl Arbitrary for ACid {
153 fn arbitrary(g: &mut Gen) -> Self {
154 ACid(crate::ipld::tests::arbitrary_cid(g))
155 }
156 }
157
158 #[quickcheck]
159 pub fn edid_link(x: ACid) -> bool { encode_decode_id(Ipld::Link(x.0)) }
160}