sp_ipld/lib.rs
1#![feature(map_first_last)]
2#![deny(
3 clippy::missing_errors_doc,
4 clippy::missing_panics_doc,
5 clippy::missing_safety_doc
6)]
7#![cfg_attr(not(any(feature = "std", test)), no_std)]
8
9#[macro_use]
10extern crate alloc;
11
12#[cfg(test)]
13extern crate quickcheck;
14#[cfg(test)]
15#[macro_use(quickcheck)]
16extern crate quickcheck_macros;
17#[cfg(test)]
18extern crate rand;
19
20pub mod codec;
21#[cfg(feature = "dag-cbor")]
22pub mod dag_cbor;
23#[cfg(feature = "dag-json")]
24pub mod dag_json;
25pub mod ipld;
26
27pub use codec::*;
28pub use ipld::*;
29
30#[cfg(test)]
31pub mod tests {
32 use super::*;
33 #[cfg(feature = "dag-cbor")]
34 use super::{
35 dag_cbor,
36 dag_cbor::DagCborCodec,
37 };
38 use bytecursor::ByteCursor;
39 use quickcheck::quickcheck;
40 use reqwest::multipart;
41 use tokio::runtime::Runtime;
42
43 #[cfg(feature = "dag-cbor")]
44 async fn dag_put_cbor(dag: Ipld) -> Result<String, reqwest::Error> {
45 let host = "http://127.0.0.1:5001";
46 let url = format!(
47 "{}{}?{}",
48 host,
49 "/api/v0/dag/put",
50 "format=dag-cbor&pin=true&input-enc=cbor&hash=blake2b-256"
51 );
52 let cbor = DagCborCodec.encode(&dag).unwrap().into_inner();
53 let client = reqwest::Client::new();
54 let form =
55 multipart::Form::new().part("file", multipart::Part::bytes(cbor));
56 let response: serde_json::Value =
57 client.post(url).multipart(form).send().await?.json().await?;
58 println!("PUT response: {:?}", response);
59
60 let ipfs_cid: String = response["Cid"]["/"].as_str().unwrap().to_string();
61 let local_cid: String = dag_cbor::cid(&dag).to_string();
62
63 if ipfs_cid == local_cid {
64 Ok(ipfs_cid)
65 }
66 else {
67 panic!("CIDs are different {} != {}", ipfs_cid, local_cid);
68 }
69 }
70
71 // #[cfg(feature = "dag-json")]
72 // pub async fn dag_put_json(dag: Ipld) -> Result<String, reqwest::Error> {
73 // let host = "http://127.0.0.1:5001";
74 // let url = format!(
75 // "{}{}?{}",
76 // host,
77 // "/api/v0/dag/put",
78 // "format=dag-cbor&pin=true&input-enc=json&hash=blake2b-256"
79 // );
80 // let cbor = DagJsonCodec.encode(&dag).unwrap().into_inner();
81 // let client = reqwest::Client::new();
82 // let form =
83 // multipart::Form::new().part("file", multipart::Part::bytes(cbor));
84 // let response: serde_json::Value =
85 // client.post(url).multipart(form).send().await?.json().await?;
86 // println!("response: {:?}", response);
87 //
88 // let ipfs_cid = response["Cid"]["/"].as_str().unwrap().to_string();
89 //
90 // assert_eq!(ipfs_cid, dag_cbor::cid(&dag).to_string());
91 //
92 // Ok(ipfs_cid)
93 // }
94
95 #[cfg(feature = "dag-cbor")]
96 async fn dag_get_cbor(cid: String) -> Result<Ipld, reqwest::Error> {
97 let host = "http://127.0.0.1:5001";
98 let url =
99 format!("{}{}?arg={}", host, "/api/v0/block/get", cid.to_string());
100 let client = reqwest::Client::new();
101 let response = client.post(url).send().await?.bytes().await?;
102 let response = response.to_vec();
103 println!("GET response: {:?}", response);
104 let ipld = DagCborCodec
105 .decode(ByteCursor::new(response))
106 .expect("invalid ipld cbor.");
107 println!("ipld: {:?}", ipld);
108
109 Ok(ipld)
110 }
111
112 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
113 // model
114 // #[cfg(feature = "dag-json")]
115 // pub async fn dag_get_json(cid: String) -> Result<Ipld, reqwest::Error> {
116 // let host = "http://127.0.0.1:5001";
117 // let url =
118 // format!("{}{}?arg={}", host, "/api/v0/dag/get", cid.to_string());
119 // let client = reqwest::Client::new();
120 // let response = client.post(url).send().await?.bytes().await?;
121 // let response = response.to_vec();
122 // println!("response: {:?}", response);
123 // let ipld = DagJsonCodec
124 // .decode(ByteCursor::new(response))
125 // .expect("invalid ipld json.");
126 // println!("ipld: {:?}", ipld);
127 //
128 // Ok(ipld)
129 // }
130
131 #[cfg(feature = "dag-cbor")]
132 async fn async_ipld_ipfs_cbor(ipld: Ipld) -> bool {
133 match dag_put_cbor(ipld.clone()).await {
134 Ok(cid) => match dag_get_cbor(cid.clone()).await {
135 Ok(new_ipld) => {
136 if ipld.clone() == new_ipld {
137 true
138 }
139 else {
140 println!("Cid: {}", cid);
141 println!("Encoded ipld: {:?}", ipld);
142 println!("Decoded ipld: {:?}", new_ipld);
143 false
144 }
145 }
146 Err(e) => {
147 println!("Error during `dag_get`: {}", e);
148 false
149 }
150 },
151 Err(e) => {
152 println!("Error during `dag_put`: {}", e);
153 false
154 }
155 }
156 }
157
158 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
159 // model
160 // #[cfg(feature = "dag-json")]
161 // async fn async_ipld_ipfs_json(ipld: Ipld) -> bool {
162 // match dag_put_json(ipld.clone()).await {
163 // Ok(cid) => match dag_get_json(cid.clone()).await {
164 // Ok(new_ipld) => {
165 // if ipld.clone() == new_ipld {
166 // true
167 // }
168 // else {
169 // println!("Cid: {}", cid);
170 // println!("Encoded ipld: {:?}", ipld);
171 // println!("Decoded ipld: {:?}", new_ipld);
172 // false
173 // }
174 // }
175 // Err(e) => {
176 // println!("Error during `dag_get`: {}", e);
177 // false
178 // }
179 // },
180 // Err(e) => {
181 // println!("Error during `dag_put`: {}", e);
182 // false
183 // }
184 // }
185 // }
186
187 #[cfg(feature = "dag-cbor")]
188 fn ipld_ipfs_cbor(ipld: Ipld) -> bool {
189 match Runtime::new() {
190 Ok(runtime) => runtime.block_on(async_ipld_ipfs_cbor(ipld)),
191 Err(e) => {
192 println!("Error creating runtime: {}", e);
193 false
194 }
195 }
196 }
197
198 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
199 // model
200 // #[cfg(feature = "dag-json")]
201 // fn ipld_ipfs_json(ipld: Ipld) -> bool {
202 // match Runtime::new() {
203 // Ok(runtime) => runtime.block_on(async_ipld_ipfs_json(ipld)),
204 // Err(e) => {
205 // println!("Error creating runtime: {}", e);
206 // false
207 // }
208 // }
209 // }
210
211 #[cfg(feature = "dag-cbor")]
212 #[ignore]
213 #[quickcheck]
214 fn null_ipfs_cbor() -> bool { ipld_ipfs_cbor(Ipld::Null) }
215
216 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
217 // model
218 // #[cfg(feature = "dag-json")]
219 // #[ignore]
220 // #[quickcheck]
221 // fn null_ipfs_json() -> bool { ipld_ipfs_json(Ipld::Null) }
222
223 #[cfg(feature = "dag-cbor")]
224 #[ignore]
225 #[quickcheck]
226 fn bool_ipfs_cbor(b: bool) -> bool { ipld_ipfs_cbor(Ipld::Bool(b)) }
227
228 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
229 // model
230 // #[cfg(feature = "dag-json")]
231 // #[ignore]
232 // #[quickcheck]
233 // fn bool_ipfs_json(b: bool) -> bool { ipld_ipfs_json(Ipld::Bool(b)) }
234
235 #[cfg(feature = "dag-cbor")]
236 #[ignore]
237 #[quickcheck]
238 fn string_ipfs_cbor(x: String) -> bool { ipld_ipfs_cbor(Ipld::String(x)) }
239
240 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
241 // model
242 // #[cfg(feature = "dag-json")]
243 // #[ignore]
244 // #[quickcheck]
245 // fn string_ipfs_json(x: String) -> bool { ipld_ipfs_json(Ipld::String(x)) }
246
247 #[cfg(feature = "dag-cbor")]
248 #[ignore]
249 #[test]
250 fn integers_ipfs_cbor() {
251 assert!(ipld_ipfs_cbor(Ipld::Integer(0i128)));
252 assert!(ipld_ipfs_cbor(Ipld::Integer(1i128)));
253 assert!(ipld_ipfs_cbor(Ipld::Integer(i128::from(i64::MAX))));
254 assert!(ipld_ipfs_cbor(Ipld::Integer(i128::from(i64::MIN))));
255 }
256
257 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
258 // model, so this test fails
259 // #[cfg(feature = "dag-json")]
260 // #[ignore]
261 // #[test]
262 // fn integers_ipfs_json() {
263 // assert!(ipld_ipfs_json(Ipld::Integer(0i128)));
264 // assert!(ipld_ipfs_json(Ipld::Integer(1i128)));
265 // assert!(ipld_ipfs_json(Ipld::Integer(i128::from(i64::MAX))));
266 // assert!(ipld_ipfs_json(Ipld::Integer(i128::from(i64::MIN))));
267 // }
268
269 #[cfg(feature = "dag-cbor")]
270 #[ignore]
271 #[quickcheck]
272 fn integer_ipfs_cbor(x: i64) -> bool {
273 ipld_ipfs_cbor(Ipld::Integer(i128::from(x)))
274 }
275
276 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
277 // model, so this test fails
278 // #[cfg(feature = "dag-json")]
279 // #[ignore]
280 // #[quickcheck]
281 // fn integer_ipfs_json(x: i64) -> bool {
282 // ipld_ipfs_json(Ipld::Integer(i128::from(x))) }
283
284 #[cfg(feature = "dag-cbor")]
285 #[ignore]
286 #[quickcheck]
287 fn ipfs_cbor(x: Ipld) -> bool { ipld_ipfs_cbor(x) }
288
289 // "input-enc=json" coerces numbers to floats and does not obey the ipld data
290 // model, so this test fails
291 // #[cfg(feature = "dag-json")]
292 // #[ignore]
293 // #[quickcheck]
294 // fn ipfs_json(x: Ipld) -> bool { ipld_ipfs_json(x) }
295}