ipfs_api_prelude/api.rs
1// Copyright 2021 rust-ipfs-api Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7//
8
9use crate::{read::LineDecoder, request, response, Backend, BoxStream};
10use async_trait::async_trait;
11use bytes::Bytes;
12use common_multipart_rfc7578::client::multipart;
13use futures::{future, AsyncRead, FutureExt, TryStreamExt};
14use std::{
15 fs::File,
16 io::{Cursor, Read},
17 path::{Path, PathBuf},
18};
19
20const FILE_DESCRIPTOR_LIMIT: usize = 127;
21
22// Implements a call to the IPFS that returns a streaming body response.
23// Implementing this in a macro is necessary because the Rust compiler
24// can't reason about the lifetime of the request instance properly. It
25// thinks that the request needs to live as long as the returned stream,
26// but in reality, the request instance is only used to build the Hyper
27// or Actix request.
28//
29macro_rules! impl_stream_api_response {
30 (($self:ident, $req:expr, $form:expr) => $call:ident) => {
31 impl_stream_api_response! {
32 ($self, $req, $form) |req| => { $self.$call(req) }
33 }
34 };
35 (($self:ident, $req:expr, $form:expr) |$var:ident| => $impl:block) => {
36 match $self.build_base_request($req, $form) {
37 Ok($var) => $impl,
38 Err(e) => Box::new(future::err(e).into_stream()),
39 }
40 };
41}
42
43#[cfg_attr(feature = "with-send-sync", async_trait)]
44#[cfg_attr(not(feature = "with-send-sync"), async_trait(?Send))]
45pub trait IpfsApi: Backend {
46 /// Add file to Ipfs.
47 ///
48 /// # Examples
49 ///
50 /// ```no_run
51 /// use ipfs_api::{IpfsApi, IpfsClient};
52 /// use std::io::Cursor;
53 ///
54 /// let client = IpfsClient::default();
55 /// let data = Cursor::new("Hello World!");
56 /// let res = client.add(data);
57 /// ```
58 ///
59 async fn add<R>(&self, data: R) -> Result<response::AddResponse, Self::Error>
60 where
61 R: 'static + Read + Send + Sync + Unpin,
62 {
63 self.add_with_options(data, request::Add::default()).await
64 }
65
66 /// Add AsyncRead stream to Ipfs.
67 ///
68 /// # Examples
69 ///
70 /// ```no_run
71 /// use ipfs_api::{IpfsApi, IpfsClient};
72 /// use std::io::Cursor;
73 ///
74 /// let client = IpfsClient::default();
75 /// let data = b"Hello World!";
76 /// let res = client.add_async(&data[..]);
77 /// ```
78 ///
79 async fn add_async<R>(&self, data: R) -> Result<response::AddResponse, Self::Error>
80 where
81 R: 'static + AsyncRead + Send + Sync + Unpin,
82 {
83 self.add_async_with_options(data, request::Add::default())
84 .await
85 }
86
87 /// Add a file to IPFS with options.
88 ///
89 /// # Examples
90 ///
91 /// ```no_run
92 /// # extern crate ipfs_api;
93 /// #
94 /// use ipfs_api::{IpfsApi, IpfsClient};
95 /// use std::io::Cursor;
96 ///
97 /// # fn main() {
98 /// let client = IpfsClient::default();
99 /// let data = Cursor::new("Hello World!");
100 /// #[cfg(feature = "with-builder")]
101 /// let add = ipfs_api::request::Add::builder()
102 /// .chunker("rabin-512-1024-2048")
103 /// .build();
104 /// #[cfg(not(feature = "with-builder"))]
105 /// let add = ipfs_api::request::Add {
106 /// chunker: Some("rabin-512-1024-2048"),
107 /// ..Default::default()
108 /// };
109 /// let req = client.add_with_options(data, add);
110 /// # }
111 /// ```
112 ///
113 async fn add_with_options<R>(
114 &self,
115 data: R,
116 add: request::Add<'_>,
117 ) -> Result<response::AddResponse, Self::Error>
118 where
119 R: 'static + Read + Send + Sync + Unpin,
120 {
121 let mut form = multipart::Form::default();
122
123 form.add_reader("path", data);
124
125 self.request(add, Some(form)).await
126 }
127
128 /// Add AsyncRead stream to IPFS with options.
129 ///
130 /// # Examples
131 ///
132 /// ```no_run
133 /// # extern crate ipfs_api;
134 /// #
135 /// use ipfs_api::{IpfsApi, IpfsClient};
136 ///
137 /// # fn main() {
138 /// let client = IpfsClient::default();
139 /// let data = b"Hello World!";
140 /// #[cfg(feature = "with-builder")]
141 /// let add = ipfs_api::request::Add::builder()
142 /// .chunker("rabin-512-1024-2048")
143 /// .build();
144 /// #[cfg(not(feature = "with-builder"))]
145 /// let add = ipfs_api::request::Add {
146 /// chunker: Some("rabin-512-1024-2048"),
147 /// ..Default::default()
148 /// };
149 /// let req = client.add_async_with_options(&data[..], add);
150 /// # }
151 /// ```
152 ///
153 async fn add_async_with_options<R>(
154 &self,
155 data: R,
156 add: request::Add<'_>,
157 ) -> Result<response::AddResponse, Self::Error>
158 where
159 R: 'static + AsyncRead + Send + Sync + Unpin,
160 {
161 let mut form = multipart::Form::default();
162
163 form.add_async_reader("path", data);
164
165 self.request(add, Some(form)).await
166 }
167
168 /// Add files using multipart::Form
169 ///
170 /// # Examples
171 ///
172 /// ```no_run
173 /// use ipfs_api::{IpfsApi, IpfsClient, Form};
174 /// use common_multipart_rfc7578::client::multipart;
175 /// use std::io::Cursor;
176 ///
177 /// #[cfg(feature = "with-builder")]
178 /// let add = ipfs_api::request::Add::builder()
179 /// .wrap_with_directory(true)
180 /// .build();
181 /// #[cfg(not(feature = "with-builder"))]
182 /// let add = ipfs_api::request::Add {
183 /// wrap_with_directory: Some(true),
184 /// ..Default::default()
185 /// };
186 ///
187 /// let mut form = Form::default();
188 /// form.add_reader_file("path", Cursor::new(Vec::new()), "file.txt");
189 ///
190 /// let client = IpfsClient::default();
191 /// let res = client.add_with_form(form, add);
192 /// ```
193 async fn add_with_form<F>(
194 &self,
195 form: F,
196 add: request::Add<'_>,
197 ) -> Result<Vec<response::AddResponse>, Self::Error>
198 where
199 F: Into<multipart::Form<'static>> + Send,
200 {
201 let req = self.build_base_request(add, Some(form.into()))?;
202 self.request_stream_json(req).try_collect().await
203 }
204
205 /// Add a path to Ipfs. Can be a file or directory.
206 /// A hard limit of 128 open file descriptors is set such
207 /// that any small additional files are stored in-memory.
208 ///
209 /// # Examples
210 ///
211 /// ```no_run
212 /// use ipfs_api::{IpfsApi, IpfsClient};
213 ///
214 /// let client = IpfsClient::default();
215 /// let path = "./src";
216 /// let res = client.add_path(path);
217 /// ```
218 ///
219 async fn add_path<P>(&self, path: P) -> Result<Vec<response::AddResponse>, Self::Error>
220 where
221 P: AsRef<Path> + Send,
222 {
223 let prefix = path.as_ref().parent();
224 let mut paths_to_add: Vec<(PathBuf, u64)> = vec![];
225
226 for path in walkdir::WalkDir::new(path.as_ref()) {
227 match path {
228 Ok(entry) if entry.file_type().is_file() => {
229 let file_size = entry
230 .metadata()
231 .map(|metadata| metadata.len())
232 .map_err(|e| crate::Error::Io(e.into()))?;
233
234 paths_to_add.push((entry.path().to_path_buf(), file_size));
235 }
236 Ok(_) => (),
237 Err(e) => return Err(crate::Error::Io(e.into()).into()),
238 }
239 }
240
241 paths_to_add.sort_unstable_by(|(_, a), (_, b)| a.cmp(b).reverse());
242
243 let mut it = 0;
244 let mut form = multipart::Form::default();
245
246 for (path, file_size) in paths_to_add {
247 let mut file = File::open(&path).map_err(crate::Error::Io)?;
248 let file_name = match prefix {
249 Some(prefix) => path.strip_prefix(prefix).unwrap(),
250 None => path.as_path(),
251 }
252 .to_string_lossy();
253
254 if it < FILE_DESCRIPTOR_LIMIT {
255 form.add_reader_file("path", file, file_name);
256
257 it += 1;
258 } else {
259 let mut buf = Vec::with_capacity(file_size as usize);
260 let _ = file.read_to_end(&mut buf).map_err(crate::Error::Io)?;
261
262 form.add_reader_file("path", Cursor::new(buf), file_name);
263 }
264 }
265
266 let req = self.build_base_request(request::Add::default(), Some(form))?;
267
268 self.request_stream_json(req).try_collect().await
269 }
270
271 /// Returns the current ledger for a peer.
272 ///
273 /// # Examples
274 ///
275 /// ```no_run
276 /// use ipfs_api::{IpfsApi, IpfsClient};
277 ///
278 /// let client = IpfsClient::default();
279 /// let res = client.bitswap_ledger("QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ");
280 /// ```
281 ///
282 async fn bitswap_ledger(
283 &self,
284 peer: &str,
285 ) -> Result<response::BitswapLedgerResponse, Self::Error> {
286 self.request(request::BitswapLedger { peer }, None).await
287 }
288
289 /// Triggers a reprovide.
290 ///
291 /// # Examples
292 ///
293 /// ```no_run
294 /// use ipfs_api::{IpfsApi, IpfsClient};
295 ///
296 /// let client = IpfsClient::default();
297 /// let res = client.bitswap_reprovide();
298 /// ```
299 ///
300 async fn bitswap_reprovide(&self) -> Result<response::BitswapReprovideResponse, Self::Error> {
301 self.request_empty(request::BitswapReprovide, None).await
302 }
303
304 /// Returns some stats about the bitswap agent.
305 ///
306 /// # Examples
307 ///
308 /// ```no_run
309 /// use ipfs_api::{IpfsApi, IpfsClient};
310 ///
311 /// let client = IpfsClient::default();
312 /// let res = client.bitswap_stat();
313 /// ```
314 ///
315 async fn bitswap_stat(&self) -> Result<response::BitswapStatResponse, Self::Error> {
316 self.request(request::BitswapStat, None).await
317 }
318
319 /// Remove a given block from your wantlist.
320 ///
321 /// # Examples
322 ///
323 /// ```no_run
324 /// use ipfs_api::{IpfsApi, IpfsClient};
325 ///
326 /// let client = IpfsClient::default();
327 /// let res = client.bitswap_unwant("QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA");
328 /// ```
329 ///
330 async fn bitswap_unwant(
331 &self,
332 key: &str,
333 ) -> Result<response::BitswapUnwantResponse, Self::Error> {
334 self.request_empty(request::BitswapUnwant { key }, None)
335 .await
336 }
337
338 /// Shows blocks on the wantlist for you or the specified peer.
339 ///
340 /// # Examples
341 ///
342 /// ```no_run
343 /// use ipfs_api::{IpfsApi, IpfsClient};
344 ///
345 /// let client = IpfsClient::default();
346 /// let res = client.bitswap_wantlist(
347 /// Some("QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ")
348 /// );
349 /// ```
350 ///
351 async fn bitswap_wantlist(
352 &self,
353 peer: Option<&str>,
354 ) -> Result<response::BitswapWantlistResponse, Self::Error> {
355 self.request(request::BitswapWantlist { peer }, None).await
356 }
357
358 /// Gets a raw IPFS block.
359 ///
360 /// # Examples
361 ///
362 /// ```no_run
363 /// use futures::TryStreamExt;
364 /// use ipfs_api::{IpfsApi, IpfsClient};
365 ///
366 /// let client = IpfsClient::default();
367 /// let hash = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
368 /// let res = client
369 /// .block_get(hash)
370 /// .map_ok(|chunk| chunk.to_vec())
371 /// .try_concat();
372 /// ```
373 ///
374 fn block_get(&self, hash: &str) -> BoxStream<Bytes, Self::Error> {
375 impl_stream_api_response! {
376 (self, request::BlockGet { hash }, None) => request_stream_bytes
377 }
378 }
379
380 /// Store input as an IPFS block.
381 ///
382 /// # Examples
383 ///
384 /// ```no_run
385 /// use ipfs_api::{IpfsApi, IpfsClient};
386 /// use std::io::Cursor;
387 ///
388 /// let client = IpfsClient::default();
389 /// let data = Cursor::new("Hello World!");
390 /// let res = client.block_put(data);
391 /// ```
392 ///
393 async fn block_put<R>(&self, data: R) -> Result<response::BlockPutResponse, Self::Error>
394 where
395 R: 'static + Read + Send + Sync + Unpin,
396 {
397 self.block_put_with_options(data, request::BlockPut::default())
398 .await
399 }
400
401 /// Store input as an IPFS block with options.
402 ///
403 /// # Examples
404 ///
405 /// ```no_run
406 /// use ipfs_api::{IpfsApi, IpfsClient};
407 /// use std::io::Cursor;
408 ///
409 /// #[cfg(feature = "with-builder")]
410 /// let options = ipfs_api::request::BlockPut::builder()
411 /// .mhtype("sha3_384")
412 /// .mhlen(48)
413 /// .build();
414 /// #[cfg(not(feature = "with-builder"))]
415 /// let options = ipts_api::request::BlockPut {
416 /// mhtype: "sha3_384",
417 /// mhlen: 48,
418 /// ..Default::default()
419 /// };
420 /// let client = IpfsClient::default();
421 /// let data = Cursor::new("Hello World!");
422 /// let res = client.block_put_with_options(data, options);
423 /// ```
424 ///
425 async fn block_put_with_options<R>(
426 &self,
427 data: R,
428 options: request::BlockPut<'async_trait>,
429 ) -> Result<response::BlockPutResponse, Self::Error>
430 where
431 R: 'static + Read + Send + Sync + Unpin,
432 {
433 let mut form = multipart::Form::default();
434
435 form.add_reader("data", data);
436
437 self.request(options, Some(form)).await
438 }
439
440 /// Removes an IPFS block.
441 ///
442 /// # Examples
443 ///
444 /// ```no_run
445 /// use ipfs_api::{IpfsApi, IpfsClient};
446 ///
447 /// let client = IpfsClient::default();
448 /// let res = client.block_rm("QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA");
449 /// ```
450 ///
451 async fn block_rm(&self, hash: &str) -> Result<response::BlockRmResponse, Self::Error> {
452 self.request(request::BlockRm { hash }, None).await
453 }
454
455 /// Prints information about a raw IPFS block.
456 ///
457 /// # Examples
458 ///
459 /// ```no_run
460 /// use ipfs_api::{IpfsApi, IpfsClient};
461 ///
462 /// let client = IpfsClient::default();
463 /// let res = client.block_stat("QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA");
464 /// ```
465 ///
466 async fn block_stat(&self, hash: &str) -> Result<response::BlockStatResponse, Self::Error> {
467 self.request(request::BlockStat { hash }, None).await
468 }
469
470 /// Add default peers to the bootstrap list.
471 ///
472 /// # Examples
473 ///
474 /// ```no_run
475 /// use ipfs_api::{IpfsApi, IpfsClient};
476 ///
477 /// let client = IpfsClient::default();
478 /// let res = client.bootstrap_add_default();
479 /// ```
480 ///
481 async fn bootstrap_add_default(
482 &self,
483 ) -> Result<response::BootstrapAddDefaultResponse, Self::Error> {
484 self.request(request::BootstrapAddDefault, None).await
485 }
486
487 /// Lists peers in bootstrap list.
488 ///
489 /// # Examples
490 ///
491 /// ```no_run
492 /// use ipfs_api::{IpfsApi, IpfsClient};
493 ///
494 /// let client = IpfsClient::default();
495 /// let res = client.bootstrap_list();
496 /// ```
497 ///
498 async fn bootstrap_list(&self) -> Result<response::BootstrapListResponse, Self::Error> {
499 self.request(request::BootstrapList, None).await
500 }
501
502 /// Removes all peers in bootstrap list.
503 ///
504 /// # Examples
505 ///
506 /// ```no_run
507 /// use ipfs_api::{IpfsApi, IpfsClient};
508 ///
509 /// let client = IpfsClient::default();
510 /// let res = client.bootstrap_rm_all();
511 /// ```
512 ///
513 async fn bootstrap_rm_all(&self) -> Result<response::BootstrapRmAllResponse, Self::Error> {
514 self.request(request::BootstrapRmAll, None).await
515 }
516
517 /// Returns the contents of an Ipfs object.
518 ///
519 /// # Examples
520 ///
521 /// ```no_run
522 /// use futures::TryStreamExt;
523 /// use ipfs_api::{IpfsApi, IpfsClient};
524 ///
525 /// let client = IpfsClient::default();
526 /// let hash = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
527 /// let res = client
528 /// .cat(hash)
529 /// .map_ok(|chunk| chunk.to_vec())
530 /// .try_concat();
531 /// ```
532 ///
533 fn cat(&self, path: &str) -> BoxStream<Bytes, Self::Error> {
534 let offset = None;
535 let length = None;
536 impl_stream_api_response! {
537 (self, request::Cat { path, offset, length }, None) => request_stream_bytes
538 }
539 }
540
541 /// Returns the the specified range of bytes of an Ipfs object.
542 ///
543 /// # Examples
544 ///
545 /// ```no_run
546 /// use futures::TryStreamExt;
547 /// use ipfs_api::{IpfsApi, IpfsClient};
548 ///
549 /// let client = IpfsClient::default();
550 /// let hash = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
551 /// let offset = 0;
552 /// let length = 10;
553 ///
554 /// let res = client
555 /// .cat_range(hash, offset, length)
556 /// .map_ok(|chunk| chunk.to_vec())
557 /// .try_concat();
558 ///
559 /// ```
560 ///
561 fn cat_range(
562 &self,
563 path: &str,
564 _offset: usize,
565 _length: usize,
566 ) -> BoxStream<Bytes, Self::Error> {
567 let offset = Some(_offset);
568 let length = Some(_length);
569 impl_stream_api_response! {
570 (self, request::Cat { path, offset, length }, None) => request_stream_bytes
571 }
572 }
573
574 /// List available commands that the server accepts.
575 ///
576 /// ```no_run
577 /// use ipfs_api::{IpfsApi, IpfsClient};
578 ///
579 /// let client = IpfsClient::default();
580 /// let res = client.commands();
581 /// ```
582 ///
583 async fn commands(&self) -> Result<response::CommandsResponse, Self::Error> {
584 self.request(request::Commands, None).await
585 }
586
587 /// Get ipfs config strings.
588 ///
589 /// ```no_run
590 /// use ipfs_api::{IpfsApi, IpfsClient};
591 ///
592 /// let client = IpfsClient::default();
593 /// let res = client.config_get_string("Identity.PeerID");
594 /// ```
595 ///
596 async fn config_get_string(&self, key: &str) -> Result<response::ConfigResponse, Self::Error> {
597 self.request(
598 request::Config {
599 key,
600 value: None,
601 boolean: None,
602 stringified_json: None,
603 },
604 None,
605 )
606 .await
607 }
608
609 /// Get ipfs config booleans.
610 ///
611 /// ```no_run
612 /// use ipfs_api::{IpfsApi, IpfsClient};
613 ///
614 /// let client = IpfsClient::default();
615 /// let res = client.config_get_bool("Datastore.HashOnRead");
616 /// ```
617 ///
618 async fn config_get_bool(&self, key: &str) -> Result<response::ConfigResponse, Self::Error> {
619 self.request(
620 request::Config {
621 key,
622 value: None,
623 boolean: None,
624 stringified_json: None,
625 },
626 None,
627 )
628 .await
629 }
630
631 /// Get ipfs config json.
632 ///
633 /// ```no_run
634 /// use ipfs_api::{IpfsApi, IpfsClient};
635 ///
636 /// let client = IpfsClient::default();
637 /// let res = client.config_get_json("Mounts");
638 /// ```
639 ///
640 async fn config_get_json(&self, key: &str) -> Result<response::ConfigResponse, Self::Error> {
641 self.request(
642 request::Config {
643 key,
644 value: None,
645 boolean: None,
646 stringified_json: None,
647 },
648 None,
649 )
650 .await
651 }
652
653 /// Set ipfs config string.
654 ///
655 /// ```no_run
656 /// use ipfs_api::{IpfsApi, IpfsClient};
657 ///
658 /// let client = IpfsClient::default();
659 /// let res = client.config_set_string("Routing.Type", "dht");
660 /// ```
661 ///
662 async fn config_set_string(
663 &self,
664 key: &str,
665 value: &str,
666 ) -> Result<response::ConfigResponse, Self::Error> {
667 self.request(
668 request::Config {
669 key,
670 value: Some(value),
671 boolean: None,
672 stringified_json: None,
673 },
674 None,
675 )
676 .await
677 }
678
679 /// Set ipfs config boolean.
680 ///
681 /// ```no_run
682 /// use ipfs_api::{IpfsApi, IpfsClient};
683 ///
684 /// let client = IpfsClient::default();
685 /// let res = client.config_set_bool("Pubsub.DisableSigning", false);
686 /// ```
687 ///
688 async fn config_set_bool(
689 &self,
690 key: &str,
691 value: bool,
692 ) -> Result<response::ConfigResponse, Self::Error> {
693 self.request(
694 request::Config {
695 key,
696 value: Some(&value.to_string()),
697 boolean: Some(true),
698 stringified_json: None,
699 },
700 None,
701 )
702 .await
703 }
704
705 /// Set ipfs config json.
706 ///
707 /// ```no_run
708 /// use ipfs_api::{IpfsApi, IpfsClient};
709 ///
710 /// let client = IpfsClient::default();
711 /// let res = client.config_set_json("Discovery", r#"{"MDNS":{"Enabled":true,"Interval":10}}"#);
712 /// ```
713 ///
714 async fn config_set_json(
715 &self,
716 key: &str,
717 value: &str,
718 ) -> Result<response::ConfigResponse, Self::Error> {
719 self.request(
720 request::Config {
721 key,
722 value: Some(value),
723 boolean: None,
724 stringified_json: Some(true),
725 },
726 None,
727 )
728 .await
729 }
730
731 /// Opens the config file for editing (on the server).
732 ///
733 /// ```no_run
734 /// use ipfs_api::{IpfsApi, IpfsClient};
735 ///
736 /// let client = IpfsClient::default();
737 /// let res = client.config_edit();
738 /// ```
739 ///
740 async fn config_edit(&self) -> Result<response::ConfigEditResponse, Self::Error> {
741 self.request(request::ConfigEdit, None).await
742 }
743
744 /// Replace the config file.
745 ///
746 /// ```no_run
747 /// use ipfs_api::{IpfsApi, IpfsClient};
748 /// use std::io::Cursor;
749 ///
750 /// let client = IpfsClient::default();
751 /// let config = Cursor::new("{..json..}");
752 /// let res = client.config_replace(config);
753 /// ```
754 ///
755 async fn config_replace<R>(
756 &self,
757 data: R,
758 ) -> Result<response::ConfigReplaceResponse, Self::Error>
759 where
760 R: 'static + Read + Send + Sync + Unpin,
761 {
762 let mut form = multipart::Form::default();
763
764 form.add_reader("file", data);
765
766 self.request_empty(request::ConfigReplace, Some(form)).await
767 }
768
769 /// Show the current config of the server.
770 ///
771 /// Returns an unparsed json string, due to an unclear spec.
772 ///
773 /// ```no_run
774 /// use ipfs_api::{IpfsApi, IpfsClient};
775 ///
776 /// let client = IpfsClient::default();
777 /// let res = client.config_show();
778 /// ```
779 ///
780 async fn config_show(&self) -> Result<response::ConfigShowResponse, Self::Error> {
781 self.request_string(request::ConfigShow, None).await
782 }
783
784 /// Returns information about a dag node in Ipfs.
785 ///
786 /// ```no_run
787 /// use futures::TryStreamExt;
788 /// use ipfs_api::{IpfsApi, IpfsClient};
789 ///
790 /// let client = IpfsClient::default();
791 /// let hash = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
792 /// let res = client
793 /// .dag_get(hash)
794 /// .map_ok(|chunk| chunk.to_vec())
795 /// .try_concat();
796 /// ```
797 ///
798 fn dag_get(&self, path: &str) -> BoxStream<Bytes, Self::Error> {
799 self.dag_get_with_options(request::DagGet {
800 path,
801 ..Default::default()
802 })
803 }
804
805 /// Returns information about a dag node in Ipfs with options.
806 ///
807 /// ```no_run
808 /// use futures::TryStreamExt;
809 /// use ipfs_api::{request::{DagCodec, DagGet}, IpfsApi, IpfsClient};
810 ///
811 /// let client = IpfsClient::default();
812 /// let hash = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
813 /// #[cfg(feature = "with-builder")]
814 /// let options = DagGet::builder().path(hash).codec(DagCodec::Cbor).build();
815 /// #[cfg(not(feature = "with-builder"))]
816 /// let options = DagGet {
817 /// path: hash,
818 /// codec: DagCodec::Cbor,
819 /// };
820 /// client.dag_get_with_options(options)
821 /// .map_ok(|chunk| chunk.to_vec())
822 /// .try_concat();
823 /// ```
824 ///
825 fn dag_get_with_options(&self, options: request::DagGet) -> BoxStream<Bytes, Self::Error> {
826 impl_stream_api_response! {
827 (self, options, None) => request_stream_bytes
828 }
829 }
830
831 /// Add a DAG node to Ipfs.
832 ///
833 /// ```no_run
834 /// use ipfs_api::{IpfsApi, IpfsClient};
835 /// use std::io::Cursor;
836 ///
837 /// let client = IpfsClient::default();
838 /// let data = Cursor::new(r#"{ "hello" : "world" }"#);
839 /// let res = client.dag_put(data);
840 /// ```
841 ///
842 async fn dag_put<R>(&self, data: R) -> Result<response::DagPutResponse, Self::Error>
843 where
844 R: 'static + Read + Send + Sync + Unpin,
845 {
846 self.dag_put_with_options(data, request::DagPut::default())
847 .await
848 }
849
850 /// Add a DAG node to Ipfs with options.
851 ///
852 /// ```no_run
853 /// use ipfs_api::{IpfsApi, IpfsClient};
854 /// use std::io::Cursor;
855 /// use ipfs_api::request::{DagCodec, DagPut};
856 ///
857 /// let client = IpfsClient::default();
858 /// let data = Cursor::new(r#"{ "hello" : "world" }"#);
859 /// let dag_put = DagPut::builder()
860 /// .input_codec(DagCodec::Json)
861 /// .pin(false)
862 /// .build();
863 /// let res = client.dag_put_with_options(data, dag_put);
864 /// ```
865 ///
866 async fn dag_put_with_options<'a, R>(
867 &self,
868 data: R,
869 options: request::DagPut<'a>,
870 ) -> Result<response::DagPutResponse, Self::Error>
871 where
872 R: 'static + Read + Send + Sync + Unpin,
873 {
874 let mut form = multipart::Form::default();
875
876 form.add_reader("object data", data);
877
878 self.request(options, Some(form)).await
879 }
880
881 // TODO /dag/resolve
882
883 /// Query the DHT for all of the multiaddresses associated with a Peer ID.
884 ///
885 /// ```no_run
886 /// use futures::TryStreamExt;
887 /// use ipfs_api::{IpfsApi, IpfsClient};
888 ///
889 /// let client = IpfsClient::default();
890 /// let peer = "QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM";
891 /// let res = client.dht_findpeer(peer).try_collect::<Vec<_>>();
892 /// ```
893 ///
894 fn dht_findpeer(&self, peer: &str) -> BoxStream<response::DhtFindPeerResponse, Self::Error> {
895 impl_stream_api_response! {
896 (self, request::DhtFindPeer { peer }, None) => request_stream_json
897 }
898 }
899
900 /// Find peers in the DHT that can provide a specific value given a key.
901 ///
902 /// ```no_run
903 /// use futures::TryStreamExt;
904 /// use ipfs_api::{IpfsApi, IpfsClient};
905 ///
906 /// let client = IpfsClient::default();
907 /// let key = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
908 /// let res = client.dht_findprovs(key).try_collect::<Vec<_>>();
909 /// ```
910 ///
911 fn dht_findprovs(&self, key: &str) -> BoxStream<response::DhtFindProvsResponse, Self::Error> {
912 impl_stream_api_response! {
913 (self, request::DhtFindProvs { key }, None) => request_stream_json
914 }
915 }
916
917 /// Query the DHT for a given key.
918 ///
919 /// ```no_run
920 /// use futures::TryStreamExt;
921 /// use ipfs_api::{IpfsApi, IpfsClient};
922 ///
923 /// let client = IpfsClient::default();
924 /// let key = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
925 /// let res = client.dht_get(key).try_collect::<Vec<_>>();
926 /// ```
927 ///
928 fn dht_get(&self, key: &str) -> BoxStream<response::DhtGetResponse, Self::Error> {
929 impl_stream_api_response! {
930 (self, request::DhtGet { key }, None) => request_stream_json
931 }
932 }
933
934 /// Announce to the network that you are providing a given value.
935 ///
936 /// ```no_run
937 /// use futures::TryStreamExt;
938 /// use ipfs_api::{IpfsApi, IpfsClient};
939 ///
940 /// let client = IpfsClient::default();
941 /// let key = "QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA";
942 /// let res = client.dht_provide(key).try_collect::<Vec<_>>();
943 /// ```
944 ///
945 fn dht_provide(&self, key: &str) -> BoxStream<response::DhtProvideResponse, Self::Error> {
946 impl_stream_api_response! {
947 (self, request::DhtProvide { key }, None) => request_stream_json
948 }
949 }
950
951 /// Write a key/value pair to the DHT.
952 ///
953 /// ```no_run
954 /// use futures::TryStreamExt;
955 /// use ipfs_api::{IpfsApi, IpfsClient};
956 ///
957 /// let client = IpfsClient::default();
958 /// let res = client.dht_put("test", "Hello World!").try_collect::<Vec<_>>();
959 /// ```
960 ///
961 fn dht_put(&self, key: &str, value: &str) -> BoxStream<response::DhtPutResponse, Self::Error> {
962 impl_stream_api_response! {
963 (self, request::DhtPut { key, value }, None) => request_stream_json
964 }
965 }
966
967 /// Find the closest peer given the peer ID by querying the DHT.
968 ///
969 /// ```no_run
970 /// use futures::TryStreamExt;
971 /// use ipfs_api::{IpfsApi, IpfsClient};
972 ///
973 /// let client = IpfsClient::default();
974 /// let peer = "QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM";
975 /// let res = client.dht_query(peer).try_collect::<Vec<_>>();
976 /// ```
977 ///
978 fn dht_query(&self, peer: &str) -> BoxStream<response::DhtQueryResponse, Self::Error> {
979 impl_stream_api_response! {
980 (self, request::DhtQuery { peer }, None) => request_stream_json
981 }
982 }
983
984 /// Clear inactive requests from the log.
985 ///
986 /// ```no_run
987 /// use ipfs_api::{IpfsApi, IpfsClient};
988 ///
989 /// let client = IpfsClient::default();
990 /// let res = client.diag_cmds_clear();
991 /// ```
992 ///
993 async fn diag_cmds_clear(&self) -> Result<response::DiagCmdsClearResponse, Self::Error> {
994 self.request_empty(request::DiagCmdsClear, None).await
995 }
996
997 /// Set how long to keep inactive requests in the log.
998 ///
999 /// ```no_run
1000 /// use ipfs_api::{IpfsApi, IpfsClient};
1001 ///
1002 /// let client = IpfsClient::default();
1003 /// let res = client.diag_cmds_set_time("1m");
1004 /// ```
1005 ///
1006 async fn diag_cmds_set_time(
1007 &self,
1008 time: &str,
1009 ) -> Result<response::DiagCmdsSetTimeResponse, Self::Error> {
1010 self.request_empty(request::DiagCmdsSetTime { time }, None)
1011 .await
1012 }
1013
1014 /// Print system diagnostic information.
1015 ///
1016 /// Note: There isn't good documentation on what this call is supposed to return.
1017 /// It might be platform dependent, but if it isn't, this can be fixed to return
1018 /// an actual object.
1019 ///
1020 /// ```no_run
1021 /// use ipfs_api::{IpfsApi, IpfsClient};
1022 ///
1023 /// let client = IpfsClient::default();
1024 /// let res = client.diag_sys();
1025 /// ```
1026 ///
1027 async fn diag_sys(&self) -> Result<response::DiagSysResponse, Self::Error> {
1028 self.request_string(request::DiagSys, None).await
1029 }
1030
1031 /// Resolve DNS link.
1032 ///
1033 /// ```no_run
1034 /// use ipfs_api::{IpfsApi, IpfsClient};
1035 ///
1036 /// let client = IpfsClient::default();
1037 /// let res = client.dns("ipfs.io", true);
1038 /// ```
1039 ///
1040 async fn dns(&self, link: &str, recursive: bool) -> Result<response::DnsResponse, Self::Error> {
1041 self.request(request::Dns { link, recursive }, None).await
1042 }
1043
1044 /// List directory for Unix filesystem objects.
1045 ///
1046 /// ```no_run
1047 /// use ipfs_api::{IpfsApi, IpfsClient};
1048 ///
1049 /// let client = IpfsClient::default();
1050 /// let res = client.file_ls("/ipns/ipfs.io");
1051 /// ```
1052 ///
1053 async fn file_ls(&self, path: &str) -> Result<response::FileLsResponse, Self::Error> {
1054 self.request(request::FileLs { path }, None).await
1055 }
1056
1057 /// Copy files into MFS.
1058 ///
1059 /// ```no_run
1060 /// use ipfs_api::{IpfsApi, IpfsClient};
1061 ///
1062 /// let client = IpfsClient::default();
1063 /// let res = client.files_cp("/path/to/file", "/dest");
1064 /// ```
1065 ///
1066 async fn files_cp(
1067 &self,
1068 path: &str,
1069 dest: &str,
1070 ) -> Result<response::FilesCpResponse, Self::Error> {
1071 self.files_cp_with_options(request::FilesCp {
1072 path,
1073 dest,
1074 ..Default::default()
1075 })
1076 .await
1077 }
1078
1079 /// Copy files into MFS.
1080 ///
1081 /// ```no_run
1082 /// use ipfs_api::{IpfsApi, IpfsClient};
1083 ///
1084 /// let client = IpfsClient::default();
1085 /// let res = client.files_cp("/path/to/file", "/dest");
1086 /// ```
1087 ///
1088 async fn files_cp_with_options(
1089 &self,
1090 options: request::FilesCp<'_>,
1091 ) -> Result<response::FilesCpResponse, Self::Error> {
1092 self.request_empty(options, None).await
1093 }
1094
1095 /// Flush a path's data to disk.
1096 ///
1097 /// ```no_run
1098 /// use ipfs_api::{IpfsApi, IpfsClient};
1099 ///
1100 /// let client = IpfsClient::default();
1101 /// let res = client.files_flush(None);
1102 /// let res = client.files_flush(Some("/tmp"));
1103 /// ```
1104 ///
1105 async fn files_flush(
1106 &self,
1107 path: Option<&str>,
1108 ) -> Result<response::FilesFlushResponse, Self::Error> {
1109 self.request_empty(request::FilesFlush { path }, None).await
1110 }
1111
1112 /// List directories in MFS.
1113 ///
1114 /// ```no_run
1115 /// use ipfs_api::{IpfsApi, IpfsClient};
1116 ///
1117 /// let client = IpfsClient::default();
1118 /// let res = client.files_ls(None);
1119 /// let res = client.files_ls(Some("/tmp"));
1120 /// ```
1121 ///
1122 async fn files_ls(&self, path: Option<&str>) -> Result<response::FilesLsResponse, Self::Error> {
1123 self.files_ls_with_options(request::FilesLs {
1124 path,
1125 ..Default::default()
1126 })
1127 .await
1128 }
1129
1130 /// List directories in MFS..
1131 ///
1132 /// ```no_run
1133 /// use ipfs_api::{IpfsApi, IpfsClient};
1134 ///
1135 /// let client = IpfsClient::default();
1136 /// #[cfg(feature = "with-builder")]
1137 /// let req = ipfs_api::request::FilesLs::builder()
1138 /// // .path("/") // defaults to /
1139 /// .unsorted(false)
1140 /// .long(true)
1141 /// .build();
1142 /// #[cfg(not(feature = "with-builder"))]
1143 /// let req = ipfs_api::request::FilesLs {
1144 /// path: None, // defaults to /
1145 /// unsorted: Some(false),
1146 /// long: Some(true),
1147 /// };
1148 /// let res = client.files_ls_with_options(req);
1149 /// ```
1150 ///
1151 /// Defaults to `-U`, so the output is unsorted.
1152 ///
1153 async fn files_ls_with_options(
1154 &self,
1155 options: request::FilesLs<'_>,
1156 ) -> Result<response::FilesLsResponse, Self::Error> {
1157 self.request(options, None).await
1158 }
1159
1160 /// Make directories in MFS.
1161 ///
1162 /// ```no_run
1163 /// use ipfs_api::{IpfsApi, IpfsClient};
1164 ///
1165 /// let client = IpfsClient::default();
1166 /// let res = client.files_mkdir("/test", false);
1167 /// let res = client.files_mkdir("/test/nested/dir", true);
1168 /// ```
1169 ///
1170 async fn files_mkdir(
1171 &self,
1172 path: &str,
1173 parents: bool,
1174 ) -> Result<response::FilesMkdirResponse, Self::Error> {
1175 self.files_mkdir_with_options(request::FilesMkdir {
1176 path,
1177 parents: Some(parents),
1178 ..Default::default()
1179 })
1180 .await
1181 }
1182
1183 /// Make directories in MFS.
1184 ///
1185 /// ```no_run
1186 /// use ipfs_api::{IpfsApi, IpfsClient};
1187 ///
1188 /// let client = IpfsClient::default();
1189 /// #[cfg(feature = "with-builder")]
1190 /// let req = ipfs_api::request::FilesMkdir::builder()
1191 /// .path("/test/nested/dir")
1192 /// .parents(true)
1193 /// .flush(false)
1194 /// .build();
1195 /// #[cfg(not(feature = "with-builder"))]
1196 /// let req = ipfs_api::request::FilesMkdir {
1197 /// path: "/test/nested/dir",
1198 /// parents: Some(true),
1199 /// flush: Some(false),
1200 /// .. Default::default()
1201 /// };
1202 /// let res = client.files_mkdir_with_options(req);
1203 /// ```
1204 ///
1205 async fn files_mkdir_with_options(
1206 &self,
1207 options: request::FilesMkdir<'_>,
1208 ) -> Result<response::FilesMkdirResponse, Self::Error> {
1209 self.request_empty(options, None).await
1210 }
1211
1212 /// Copy files into MFS.
1213 ///
1214 /// ```no_run
1215 /// use ipfs_api::{IpfsApi, IpfsClient};
1216 ///
1217 /// let client = IpfsClient::default();
1218 /// let res = client.files_mv("/test/tmp.json", "/test/file.json");
1219 /// ```
1220 ///
1221 async fn files_mv(
1222 &self,
1223 path: &str,
1224 dest: &str,
1225 ) -> Result<response::FilesMvResponse, Self::Error> {
1226 self.files_mv_with_options(request::FilesMv {
1227 path,
1228 dest,
1229 ..Default::default()
1230 })
1231 .await
1232 }
1233
1234 /// Copy files into MFS.
1235 ///
1236 /// ```no_run
1237 /// use ipfs_api::{IpfsApi, IpfsClient};
1238 ///
1239 /// let client = IpfsClient::default();
1240 /// let res = client.files_mv_with_options(
1241 /// ipfs_api::request::FilesMv {
1242 /// path: "/test/tmp.json",
1243 /// dest: "/test/file.json",
1244 /// flush: Some(false),
1245 /// }
1246 /// );
1247 /// ```
1248 ///
1249 async fn files_mv_with_options(
1250 &self,
1251 options: request::FilesMv<'_>,
1252 ) -> Result<response::FilesMvResponse, Self::Error> {
1253 self.request_empty(options, None).await
1254 }
1255
1256 /// Read a file in MFS.
1257 ///
1258 /// ```no_run
1259 /// use ipfs_api::{IpfsApi, IpfsClient};
1260 ///
1261 /// let client = IpfsClient::default();
1262 /// let res = client.files_read("/test/file.json");
1263 /// ```
1264 ///
1265 fn files_read(&self, path: &str) -> BoxStream<Bytes, Self::Error> {
1266 self.files_read_with_options(request::FilesRead {
1267 path,
1268 ..request::FilesRead::default()
1269 })
1270 }
1271
1272 /// Read a file in MFS.
1273 ///
1274 /// ```no_run
1275 /// use ipfs_api::{IpfsApi, IpfsClient};
1276 ///
1277 /// let client = IpfsClient::default();
1278 /// #[cfg(feature = "with-builder")]
1279 /// let req = ipfs_api::request::FilesRead::builder()
1280 /// .path("/test/file.json")
1281 /// .offset(1024)
1282 /// .count(8)
1283 /// .build();
1284 /// #[cfg(not(feature = "with-builder"))]
1285 /// let req = ipfs_api::request::FilesRead {
1286 /// path: "/test/file.json",
1287 /// offset: Some(1024),
1288 /// count: Some(8),
1289 /// };
1290 /// let res = client.files_read_with_options(req);
1291 /// ```
1292 ///
1293 fn files_read_with_options(
1294 &self,
1295 options: request::FilesRead,
1296 ) -> BoxStream<Bytes, Self::Error> {
1297 impl_stream_api_response! { (self, options, None) => request_stream_bytes }
1298 }
1299
1300 /// Remove a file in MFS.
1301 ///
1302 /// ```no_run
1303 /// use ipfs_api::{IpfsApi, IpfsClient};
1304 ///
1305 /// let client = IpfsClient::default();
1306 /// let res = client.files_rm("/test/dir", true);
1307 /// let res = client.files_rm("/test/file.json", false);
1308 /// ```
1309 ///
1310 async fn files_rm(
1311 &self,
1312 path: &str,
1313 recursive: bool,
1314 ) -> Result<response::FilesRmResponse, Self::Error> {
1315 self.files_rm_with_options(request::FilesRm {
1316 path,
1317 recursive: Some(recursive),
1318 ..Default::default()
1319 })
1320 .await
1321 }
1322
1323 /// Remove a file in MFS.
1324 ///
1325 /// ```no_run
1326 /// use ipfs_api::{IpfsApi, IpfsClient};
1327 ///
1328 /// let client = IpfsClient::default();
1329 /// #[cfg(feature = "with-builder")]
1330 /// let req = ipfs_api::request::FilesRm::builder()
1331 /// .path("/test/somefile.json")
1332 /// .recursive(false)
1333 /// .flush(false)
1334 /// .build();
1335 /// #[cfg(not(feature = "with-builder"))]
1336 /// let req = ipfs_api::request::FilesRm {
1337 /// path: "/test/somefile.json",
1338 /// recursive: Some(false),
1339 /// flush: Some(false),
1340 /// };
1341 /// let res = client.files_rm_with_options(req);
1342 /// ```
1343 ///
1344 async fn files_rm_with_options(
1345 &self,
1346 options: request::FilesRm<'_>,
1347 ) -> Result<response::FilesRmResponse, Self::Error> {
1348 self.request_empty(options, None).await
1349 }
1350
1351 /// Display a file's status in MFS.
1352 ///
1353 /// ```no_run
1354 /// use ipfs_api::{IpfsApi, IpfsClient};
1355 ///
1356 /// let client = IpfsClient::default();
1357 /// let res = client.files_stat("/test/file.json");
1358 /// ```
1359 ///
1360 async fn files_stat(&self, path: &str) -> Result<response::FilesStatResponse, Self::Error> {
1361 self.files_stat_with_options(request::FilesStat {
1362 path,
1363 ..Default::default()
1364 })
1365 .await
1366 }
1367
1368 /// Display a file's status in MFS.
1369 ///
1370 /// ```no_run
1371 /// use ipfs_api::{IpfsApi, IpfsClient};
1372 ///
1373 /// let client = IpfsClient::default();
1374 /// let res = client.files_stat_with_options(
1375 /// ipfs_api::request::FilesStat {
1376 /// path: "/test/dir/",
1377 /// with_local: Some(true),
1378 /// }
1379 /// );
1380 /// ```
1381 ///
1382 async fn files_stat_with_options(
1383 &self,
1384 options: request::FilesStat<'_>,
1385 ) -> Result<response::FilesStatResponse, Self::Error> {
1386 self.request(options, None).await
1387 }
1388
1389 /// Write to a mutable file in the filesystem.
1390 ///
1391 /// ```no_run
1392 /// use ipfs_api::{IpfsApi, IpfsClient};
1393 /// use std::fs::File;
1394 ///
1395 /// let client = IpfsClient::default();
1396 /// let file = File::open("test.json").unwrap();
1397 /// let res = client.files_write("/test/file.json", true, true, file);
1398 /// ```
1399 ///
1400 async fn files_write<R>(
1401 &self,
1402 path: &str,
1403 create: bool,
1404 truncate: bool,
1405 data: R,
1406 ) -> Result<response::FilesWriteResponse, Self::Error>
1407 where
1408 R: 'static + Read + Send + Sync + Unpin,
1409 {
1410 let options = request::FilesWrite {
1411 path,
1412 create: Some(create),
1413 truncate: Some(truncate),
1414 ..request::FilesWrite::default()
1415 };
1416
1417 self.files_write_with_options(options, data).await
1418 }
1419
1420 /// Write to a mutable file in the filesystem.
1421 ///
1422 /// ```no_run
1423 /// use ipfs_api::{IpfsApi, IpfsClient};
1424 /// use std::io::Cursor;
1425 ///
1426 /// let client = IpfsClient::default();
1427 /// let data = Cursor::new((1..128).collect::<Vec<u8>>());
1428 /// #[cfg(feature = "with-builder")]
1429 /// let req = ipfs_api::request::FilesWrite::builder()
1430 /// .path("/test/outfile.bin")
1431 /// .create(false)
1432 /// .truncate(false)
1433 /// .offset(1 << 20)
1434 /// .flush(false)
1435 /// // see FilesWriteBuilder for the full set of options
1436 /// .build();
1437 /// #[cfg(not(feature = "with-builder"))]
1438 /// let req = ipfs_api::request::FilesWrite {
1439 /// path: "/test/outfile.bin",
1440 /// create: Some(false),
1441 /// truncate: Some(false),
1442 /// offset: Some(1 << 20),
1443 /// flush: Some(false),
1444 /// .. Default::default()
1445 /// };
1446 /// let res = client.files_write_with_options(req, data);
1447 /// ```
1448 ///
1449 async fn files_write_with_options<R>(
1450 &self,
1451 options: request::FilesWrite<'_>,
1452 data: R,
1453 ) -> Result<response::FilesWriteResponse, Self::Error>
1454 where
1455 R: 'static + Read + Send + Sync + Unpin,
1456 {
1457 let mut form = multipart::Form::default();
1458
1459 form.add_reader("data", data);
1460
1461 self.request_empty(options, Some(form)).await
1462 }
1463
1464 /// Change the cid version or hash function of the root node of a given path.
1465 ///
1466 /// ```no_run
1467 /// use ipfs_api::{IpfsApi, IpfsClient};
1468 /// use std::fs::File;
1469 ///
1470 /// let client = IpfsClient::default();
1471 /// let res = client.files_chcid("/test/", 1);
1472 /// ```
1473 ///
1474 /// Not specifying a byte `count` writes the entire input.
1475 ///
1476 async fn files_chcid(
1477 &self,
1478 path: &str,
1479 cid_version: i32,
1480 ) -> Result<response::FilesChcidResponse, Self::Error> {
1481 self.request_empty(
1482 request::FilesChcid {
1483 path: Some(path),
1484 cid_version: Some(cid_version),
1485 ..Default::default()
1486 },
1487 None,
1488 )
1489 .await
1490 }
1491
1492 /// Change the cid version or hash function of the root node of a given path.
1493 ///
1494 /// ```no_run
1495 /// use ipfs_api::{IpfsApi, IpfsClient};
1496 /// use std::fs::File;
1497 ///
1498 /// let client = IpfsClient::default();
1499 /// #[cfg(feature = "with-builder")]
1500 /// let req = ipfs_api::request::FilesChcid::builder()
1501 /// .path("/test/")
1502 /// .cid_version(1)
1503 /// .hash("sha3-512")
1504 /// .flush(true)
1505 /// .build();
1506 /// #[cfg(not(feature = "with-builder"))]
1507 /// let req = ipfs_api::request::FilesChcid {
1508 /// path: Some("/test/"),
1509 /// cid_version: Some(1),
1510 /// hash: Some("sha3-512"),
1511 /// flush: Some(false),
1512 /// };
1513 /// let res = client.files_chcid_with_options(req);
1514 /// ```
1515 ///
1516 /// Not specifying a byte `count` writes the entire input.
1517 ///
1518 async fn files_chcid_with_options(
1519 &self,
1520 options: request::FilesChcid<'_>,
1521 ) -> Result<response::FilesChcidResponse, Self::Error> {
1522 self.request_empty(options, None).await
1523 }
1524
1525 /// List blocks that are both in the filestore and standard block storage.
1526 ///
1527 /// ```no_run
1528 /// use ipfs_api::{IpfsApi, IpfsClient};
1529 ///
1530 /// let client = IpfsClient::default();
1531 /// let res = client.filestore_dups();
1532 /// ```
1533 ///
1534 fn filestore_dups(&self) -> BoxStream<response::FilestoreDupsResponse, Self::Error> {
1535 impl_stream_api_response! {
1536 (self, request::FilestoreDups, None) => request_stream_json
1537 }
1538 }
1539
1540 /// List objects in filestore.
1541 ///
1542 /// ```no_run
1543 /// use ipfs_api::{IpfsApi, IpfsClient};
1544 ///
1545 /// let client = IpfsClient::default();
1546 /// let res = client.filestore_ls(
1547 /// Some("QmYPP3BovR2m8UqCZxFbdXSit6SKgExxDkFAPLqiGsap4X")
1548 /// );
1549 /// ```
1550 ///
1551 fn filestore_ls(
1552 &self,
1553 cid: Option<&str>,
1554 ) -> BoxStream<response::FilestoreLsResponse, Self::Error> {
1555 impl_stream_api_response! {
1556 (self, request::FilestoreLs { cid }, None) => request_stream_json
1557 }
1558 }
1559
1560 /// Verify objects in filestore.
1561 ///
1562 /// ```no_run
1563 /// use ipfs_api::{IpfsApi, IpfsClient};
1564 ///
1565 /// let client = IpfsClient::default();
1566 /// let res = client.filestore_verify(None);
1567 /// ```
1568 ///
1569 fn filestore_verify(
1570 &self,
1571 cid: Option<&str>,
1572 ) -> BoxStream<response::FilestoreVerifyResponse, Self::Error> {
1573 impl_stream_api_response! {
1574 (self, request::FilestoreVerify{ cid }, None) => request_stream_json
1575 }
1576 }
1577
1578 /// Download Ipfs object.
1579 ///
1580 /// ```no_run
1581 /// use ipfs_api::{IpfsApi, IpfsClient};
1582 ///
1583 /// let client = IpfsClient::default();
1584 /// let res = client.get("/test/file.json");
1585 /// ```
1586 ///
1587 fn get(&self, path: &str) -> BoxStream<Bytes, Self::Error> {
1588 impl_stream_api_response! {
1589 (self, request::Get { path }, None) => request_stream_bytes
1590 }
1591 }
1592
1593 /// Returns information about a peer.
1594 ///
1595 /// If `peer` is `None`, returns information about you.
1596 ///
1597 /// ```no_run
1598 /// use ipfs_api::{IpfsApi, IpfsClient};
1599 ///
1600 /// let client = IpfsClient::default();
1601 /// let res = client.id(None);
1602 /// let res = client.id(Some("QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM"));
1603 /// ```
1604 ///
1605 async fn id(&self, peer: Option<&str>) -> Result<response::IdResponse, Self::Error> {
1606 self.request(request::Id { peer }, None).await
1607 }
1608
1609 /// Create a new keypair.
1610 ///
1611 /// ```no_run
1612 /// use ipfs_api::{IpfsApi, IpfsClient, KeyType};
1613 ///
1614 /// let client = IpfsClient::default();
1615 /// let res = client.key_gen("test", KeyType::Rsa, 64);
1616 /// ```
1617 ///
1618 async fn key_gen(
1619 &self,
1620 name: &str,
1621 kind: request::KeyType,
1622 size: i32,
1623 ) -> Result<response::KeyGenResponse, Self::Error> {
1624 self.request(request::KeyGen { name, kind, size }, None)
1625 .await
1626 }
1627
1628 /// List all local keypairs.
1629 ///
1630 /// ```no_run
1631 /// use ipfs_api::{IpfsApi, IpfsClient};
1632 ///
1633 /// let client = IpfsClient::default();
1634 /// let res = client.key_list();
1635 /// ```
1636 ///
1637 async fn key_list(&self) -> Result<response::KeyListResponse, Self::Error> {
1638 self.request(request::KeyList, None).await
1639 }
1640
1641 /// Rename a keypair.
1642 ///
1643 /// ```no_run
1644 /// use ipfs_api::{IpfsApi, IpfsClient};
1645 ///
1646 /// let client = IpfsClient::default();
1647 /// let res = client.key_rename("key_0", "new_name", false);
1648 /// ```
1649 ///
1650 async fn key_rename(
1651 &self,
1652 name: &str,
1653 new: &str,
1654 force: bool,
1655 ) -> Result<response::KeyRenameResponse, Self::Error> {
1656 self.request(request::KeyRename { name, new, force }, None)
1657 .await
1658 }
1659
1660 /// Remove a keypair.
1661 ///
1662 /// ```no_run
1663 /// use ipfs_api::{IpfsApi, IpfsClient};
1664 ///
1665 /// let client = IpfsClient::default();
1666 /// let res = client.key_rm("key_0");
1667 /// ```
1668 ///
1669 async fn key_rm(&self, name: &str) -> Result<response::KeyRmResponse, Self::Error> {
1670 self.request(request::KeyRm { name }, None).await
1671 }
1672
1673 /// Change the logging level for a logger.
1674 ///
1675 /// ```no_run
1676 /// use ipfs_api::{IpfsApi, IpfsClient, Logger, LoggingLevel};
1677 /// use std::borrow::Cow;
1678 ///
1679 /// let client = IpfsClient::default();
1680 /// let res = client.log_level(Logger::All, LoggingLevel::Debug);
1681 /// let res = client.log_level(
1682 /// Logger::Specific(Cow::Borrowed("web")),
1683 /// LoggingLevel::Warning
1684 /// );
1685 /// ```
1686 ///
1687 async fn log_level(
1688 &self,
1689 logger: request::Logger<'_>,
1690 level: request::LoggingLevel,
1691 ) -> Result<response::LogLevelResponse, Self::Error> {
1692 self.request(request::LogLevel { logger, level }, None)
1693 .await
1694 }
1695
1696 /// List all logging subsystems.
1697 ///
1698 /// ```no_run
1699 /// use ipfs_api::{IpfsApi, IpfsClient};
1700 ///
1701 /// let client = IpfsClient::default();
1702 /// let res = client.log_ls();
1703 /// ```
1704 ///
1705 async fn log_ls(&self) -> Result<response::LogLsResponse, Self::Error> {
1706 self.request(request::LogLs, None).await
1707 }
1708
1709 /// Read the event log.
1710 ///
1711 /// ```no_run
1712 /// use ipfs_api::{IpfsApi, IpfsClient};
1713 ///
1714 /// let client = IpfsClient::default();
1715 /// let res = client.log_tail();
1716 /// ```
1717 ///
1718 fn log_tail(&self) -> BoxStream<String, Self::Error> {
1719 impl_stream_api_response! {
1720 (self, request::LogTail, None) |req| => {
1721 self.request_stream(req, |res| {
1722 Box::new(Self::process_stream_response(res, LineDecoder).map_err(Self::Error::from))
1723 })
1724 }
1725 }
1726 }
1727
1728 /// List the contents of an Ipfs multihash.
1729 ///
1730 /// ```no_run
1731 /// use ipfs_api::{IpfsApi, IpfsClient};
1732 ///
1733 /// let client = IpfsClient::default();
1734 /// let res = client.ls("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
1735 /// ```
1736 ///
1737 async fn ls(&self, path: &str) -> Result<response::LsResponse, Self::Error> {
1738 self.request(
1739 request::Ls {
1740 path,
1741 ..Default::default()
1742 },
1743 None,
1744 )
1745 .await
1746 }
1747
1748 /// List the contents of an Ipfs multihash.
1749 ///
1750 /// ```no_run
1751 /// use ipfs_api::{IpfsApi, IpfsClient};
1752 ///
1753 /// let client = IpfsClient::default();
1754 /// #[cfg(feature = "with-builder")]
1755 /// let _ = client.ls_with_options(ipfs_api::request::Ls::builder()
1756 /// .path("/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n")
1757 /// .build()
1758 /// );
1759 /// #[cfg(not(feature = "with-builder"))]
1760 /// let _ = client.ls_with_options(ipfs_api::request::Ls {
1761 /// path: "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n",
1762 /// // Example options for fast listing
1763 /// stream: Some(true),
1764 /// resolve_type: Some(false),
1765 /// size: Some(false),
1766 /// });
1767 /// ```
1768 ///
1769 fn ls_with_options(
1770 &self,
1771 options: request::Ls<'_>,
1772 ) -> BoxStream<response::LsResponse, Self::Error> {
1773 impl_stream_api_response! {
1774 (self, options, None) => request_stream_json
1775 }
1776 }
1777
1778 // TODO /mount
1779
1780 /// Publish an IPFS path to IPNS.
1781 ///
1782 /// ```no_run
1783 /// use ipfs_api::{IpfsApi, IpfsClient};
1784 ///
1785 /// let client = IpfsClient::default();
1786 /// let res = client.name_publish(
1787 /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY",
1788 /// false,
1789 /// Some("12h"),
1790 /// None,
1791 /// None
1792 /// );
1793 /// ```
1794 ///
1795 async fn name_publish(
1796 &self,
1797 path: &str,
1798 resolve: bool,
1799 lifetime: Option<&str>,
1800 ttl: Option<&str>,
1801 key: Option<&str>,
1802 ) -> Result<response::NamePublishResponse, Self::Error> {
1803 self.request(
1804 request::NamePublish {
1805 path,
1806 resolve,
1807 lifetime,
1808 ttl,
1809 key,
1810 },
1811 None,
1812 )
1813 .await
1814 }
1815
1816 /// Resolve an IPNS name.
1817 ///
1818 /// ```no_run
1819 /// use ipfs_api::{IpfsApi, IpfsClient};
1820 ///
1821 /// let client = IpfsClient::default();
1822 /// let res = client.name_resolve(
1823 /// Some("/ipns/ipfs.io"),
1824 /// true,
1825 /// false
1826 /// );
1827 /// ```
1828 ///
1829 async fn name_resolve(
1830 &self,
1831 name: Option<&str>,
1832 recursive: bool,
1833 nocache: bool,
1834 ) -> Result<response::NameResolveResponse, Self::Error> {
1835 self.request(
1836 request::NameResolve {
1837 name,
1838 recursive,
1839 nocache,
1840 },
1841 None,
1842 )
1843 .await
1844 }
1845
1846 /// Output the raw bytes of an Ipfs object.
1847 ///
1848 /// ```no_run
1849 /// use ipfs_api::{IpfsApi, IpfsClient};
1850 ///
1851 /// let client = IpfsClient::default();
1852 /// let res = client.object_data("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
1853 /// ```
1854 ///
1855 fn object_data(&self, key: &str) -> BoxStream<Bytes, Self::Error> {
1856 impl_stream_api_response! {
1857 (self, request::ObjectData { key }, None) => request_stream_bytes
1858 }
1859 }
1860
1861 /// Returns the diff of two Ipfs objects.
1862 ///
1863 /// ```no_run
1864 /// use ipfs_api::{IpfsApi, IpfsClient};
1865 ///
1866 /// let client = IpfsClient::default();
1867 /// let res = client.object_diff(
1868 /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY",
1869 /// "/ipfs/QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA"
1870 /// );
1871 /// ```
1872 ///
1873 async fn object_diff(
1874 &self,
1875 key0: &str,
1876 key1: &str,
1877 ) -> Result<response::ObjectDiffResponse, Self::Error> {
1878 self.request(request::ObjectDiff { key0, key1 }, None).await
1879 }
1880
1881 /// Returns the data in an object.
1882 ///
1883 /// ```no_run
1884 /// use ipfs_api::{IpfsApi, IpfsClient};
1885 ///
1886 /// let client = IpfsClient::default();
1887 /// let res = client.object_get("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
1888 /// ```
1889 ///
1890 async fn object_get(&self, key: &str) -> Result<response::ObjectGetResponse, Self::Error> {
1891 self.request(request::ObjectGet { key }, None).await
1892 }
1893
1894 /// Returns the links that an object points to.
1895 ///
1896 /// ```no_run
1897 /// use ipfs_api::{IpfsApi, IpfsClient};
1898 ///
1899 /// let client = IpfsClient::default();
1900 /// let res = client.object_links("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
1901 /// ```
1902 ///
1903 async fn object_links(&self, key: &str) -> Result<response::ObjectLinksResponse, Self::Error> {
1904 self.request(request::ObjectLinks { key }, None).await
1905 }
1906
1907 /// Create a new object.
1908 ///
1909 /// ```no_run
1910 /// use ipfs_api::{IpfsApi, IpfsClient, ObjectTemplate};
1911 ///
1912 /// let client = IpfsClient::default();
1913 /// let res = client.object_new(None);
1914 /// let res = client.object_new(Some(ObjectTemplate::UnixFsDir));
1915 /// ```
1916 ///
1917 async fn object_new(
1918 &self,
1919 template: Option<request::ObjectTemplate>,
1920 ) -> Result<response::ObjectNewResponse, Self::Error> {
1921 self.request(request::ObjectNew { template }, None).await
1922 }
1923
1924 /// Add a directory link to an object.
1925 ///
1926 /// ```no_run
1927 /// use ipfs_api::{IpfsApi, IpfsClient};
1928 ///
1929 /// let client = IpfsClient::default();
1930 /// let res = client.object_patch_add_link(
1931 /// "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn",
1932 /// "hello_world.txt",
1933 /// "QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG",
1934 /// false
1935 /// );
1936 /// let res = client.object_patch_add_link(
1937 /// "QmcXu68EVrtSEQ8SoPCWAfKJ9JqY6jnZyyiizRwksnt3kv",
1938 /// "hello/dad.txt",
1939 /// "Qma1UVHKYFkk6cGo3V1VmyMxRb1Bpd9SBbXdZURk28VtND",
1940 /// true
1941 /// );
1942 /// ```
1943 ///
1944 async fn object_patch_add_link(
1945 &self,
1946 folder: &str,
1947 name: &str,
1948 key: &str,
1949 create: bool,
1950 ) -> Result<response::ObjectPatchAddLinkResponse, Self::Error> {
1951 self.request(
1952 request::ObjectPatchAddLink {
1953 folder,
1954 name,
1955 key,
1956 create,
1957 },
1958 None,
1959 )
1960 .await
1961 }
1962
1963 // TODO /object/patch/append-data
1964
1965 // TODO /object/patch/rm-link
1966
1967 // TODO /object/patch/set-data
1968
1969 // TODO /object/put
1970
1971 /// Returns the stats for an object.
1972 ///
1973 /// ```no_run
1974 /// use ipfs_api::{IpfsApi, IpfsClient};
1975 ///
1976 /// let client = IpfsClient::default();
1977 /// let res = client.object_stat("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
1978 /// ```
1979 ///
1980 async fn object_stat(&self, key: &str) -> Result<response::ObjectStatResponse, Self::Error> {
1981 self.request(request::ObjectStat { key }, None).await
1982 }
1983
1984 // TODO /p2p/listener/close
1985
1986 // TODO /p2p/listener/ls
1987
1988 // TODO /p2p/listener/open
1989
1990 // TODO /p2p/stream/close
1991
1992 // TODO /p2p/stream/dial
1993
1994 // TODO /p2p/stream/ls
1995
1996 /// Pins a new object.
1997 ///
1998 /// The "recursive" option tells the server whether to
1999 /// pin just the top-level object, or all sub-objects
2000 /// it depends on. For most cases you want it to be `true`.
2001 ///
2002 /// Does not yet implement the "progress" agument because
2003 /// reading it is kinda squirrelly.
2004 ///
2005 /// # Examples
2006 ///
2007 /// ```no_run
2008 /// use ipfs_api::{IpfsApi, IpfsClient};
2009 ///
2010 /// let client = IpfsClient::default();
2011 /// let res = client.pin_add("QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", true);
2012 /// ```
2013 ///
2014 async fn pin_add(
2015 &self,
2016 key: &str,
2017 recursive: bool,
2018 ) -> Result<response::PinAddResponse, Self::Error> {
2019 self.request(
2020 request::PinAdd {
2021 key,
2022 recursive: Some(recursive),
2023 progress: false,
2024 },
2025 None,
2026 )
2027 .await
2028 }
2029
2030 /// Returns a list of pinned objects in local storage.
2031 ///
2032 /// ```no_run
2033 /// use ipfs_api::{IpfsApi, IpfsClient};
2034 ///
2035 /// let client = IpfsClient::default();
2036 /// let res = client.pin_ls(None, None);
2037 /// let res = client.pin_ls(
2038 /// Some("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"),
2039 /// None
2040 /// );
2041 /// let res = client.pin_ls(None, Some("direct"));
2042 /// ```
2043 ///
2044 async fn pin_ls(
2045 &self,
2046 key: Option<&str>,
2047 typ: Option<&str>,
2048 ) -> Result<response::PinLsResponse, Self::Error> {
2049 self.request(request::PinLs { key, typ }, None).await
2050 }
2051
2052 /// Removes a pinned object from local storage.
2053 ///
2054 /// ```no_run
2055 /// use ipfs_api::{IpfsApi, IpfsClient};
2056 ///
2057 /// let client = IpfsClient::default();
2058 /// let res = client.pin_rm(
2059 /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY",
2060 /// false
2061 /// );
2062 /// let res = client.pin_rm(
2063 /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY",
2064 /// true
2065 /// );
2066 /// ```
2067 ///
2068 async fn pin_rm(
2069 &self,
2070 key: &str,
2071 recursive: bool,
2072 ) -> Result<response::PinRmResponse, Self::Error> {
2073 self.request(request::PinRm { key, recursive }, None).await
2074 }
2075
2076 // TODO /pin/update
2077
2078 // TODO /pin/verify
2079
2080 /// Pings a peer.
2081 ///
2082 /// ```no_run
2083 /// use ipfs_api::{IpfsApi, IpfsClient};
2084 ///
2085 /// let client = IpfsClient::default();
2086 /// let res = client.ping("QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", None);
2087 /// let res = client.ping("QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", Some(15));
2088 /// ```
2089 ///
2090 fn ping(
2091 &self,
2092 peer: &str,
2093 count: Option<i32>,
2094 ) -> BoxStream<response::PingResponse, Self::Error> {
2095 impl_stream_api_response! {
2096 (self, request::Ping { peer, count }, None) => request_stream_json
2097 }
2098 }
2099
2100 /// List subscribed pubsub topics.
2101 ///
2102 /// ```no_run
2103 /// use ipfs_api::{IpfsApi, IpfsClient};
2104 ///
2105 /// let client = IpfsClient::default();
2106 /// let res = client.pubsub_ls();
2107 /// ```
2108 ///
2109 async fn pubsub_ls(&self) -> Result<response::PubsubLsResponse, Self::Error> {
2110 self.request(request::PubsubLs, None).await
2111 }
2112
2113 /// List peers that are being published to.
2114 ///
2115 /// ```no_run
2116 /// use ipfs_api::{IpfsApi, IpfsClient};
2117 ///
2118 /// let client = IpfsClient::default();
2119 /// let res = client.pubsub_peers(Option::<String>::None);
2120 /// let res = client.pubsub_peers(Some("feed"));
2121 /// ```
2122 ///
2123 async fn pubsub_peers<T>(
2124 &self,
2125 topic: Option<T>,
2126 ) -> Result<response::PubsubPeersResponse, Self::Error>
2127 where
2128 T: AsRef<[u8]> + Send + Sync,
2129 {
2130 match topic {
2131 Some(topic) => {
2132 self.request(
2133 request::PubsubPeers {
2134 topic: Some(topic.as_ref()),
2135 },
2136 None,
2137 )
2138 .await
2139 }
2140 None => {
2141 self.request(request::PubsubPeers { topic: None }, None)
2142 .await
2143 }
2144 }
2145 }
2146
2147 /// Publish a message to a topic.
2148 ///
2149 /// ```no_run
2150 /// use ipfs_api::{IpfsApi, IpfsClient};
2151 /// use std::io::Cursor;
2152 ///
2153 /// let client = IpfsClient::default();
2154 /// let res = client.pubsub_pub("feed", Cursor::new("Hello World!"));
2155 /// ```
2156 ///
2157 async fn pubsub_pub<T, R>(
2158 &self,
2159 topic: T,
2160 data: R,
2161 ) -> Result<response::PubsubPubResponse, Self::Error>
2162 where
2163 T: AsRef<[u8]> + Send + Sync,
2164 R: 'static + Read + Send + Sync + Unpin,
2165 {
2166 let mut form = multipart::Form::default();
2167
2168 form.add_reader("data", data);
2169
2170 self.request_empty(
2171 request::PubsubPub {
2172 topic: topic.as_ref(),
2173 },
2174 Some(form),
2175 )
2176 .await
2177 }
2178
2179 /// Subscribes to a pubsub topic.
2180 ///
2181 /// ```no_run
2182 /// use ipfs_api::{IpfsApi, IpfsClient};
2183 ///
2184 /// let client = IpfsClient::default();
2185 /// let res = client.pubsub_sub("feed");
2186 /// let res = client.pubsub_sub("feed");
2187 /// ```
2188 ///
2189 fn pubsub_sub<T>(&self, topic: T) -> BoxStream<response::PubsubSubResponse, Self::Error>
2190 where
2191 T: AsRef<[u8]>,
2192 {
2193 impl_stream_api_response! {
2194 (self, request::PubsubSub { topic: topic.as_ref() }, None) => request_stream_json
2195 }
2196 }
2197
2198 /// Gets a list of local references.
2199 ///
2200 /// ```no_run
2201 /// use ipfs_api::{IpfsApi, IpfsClient};
2202 ///
2203 /// let client = IpfsClient::default();
2204 /// let res = client.refs_local();
2205 /// ```
2206 ///
2207 fn refs_local(&self) -> BoxStream<response::RefsLocalResponse, Self::Error> {
2208 impl_stream_api_response! {
2209 (self, request::RefsLocal, None) => request_stream_json
2210 }
2211 }
2212
2213 // TODO /repo/fsck
2214
2215 // TODO /repo/gc
2216
2217 // TODO /repo/stat
2218
2219 // TODO /repo/verify
2220
2221 // TODO /repo/version
2222
2223 // TODO /resolve
2224
2225 /// Shutdown the Ipfs daemon.
2226 ///
2227 /// ```no_run
2228 /// use ipfs_api::{IpfsApi, IpfsClient};
2229 ///
2230 /// let client = IpfsClient::default();
2231 /// let res = client.shutdown();
2232 /// ```
2233 ///
2234 async fn shutdown(&self) -> Result<response::ShutdownResponse, Self::Error> {
2235 self.request_empty(request::Shutdown, None).await
2236 }
2237
2238 /// Returns bitswap stats.
2239 ///
2240 /// ```no_run
2241 /// use ipfs_api::{IpfsApi, IpfsClient};
2242 ///
2243 /// let client = IpfsClient::default();
2244 /// let res = client.stats_bitswap();
2245 /// ```
2246 ///
2247 async fn stats_bitswap(&self) -> Result<response::StatsBitswapResponse, Self::Error> {
2248 self.request(request::StatsBitswap, None).await
2249 }
2250
2251 /// Returns bandwidth stats.
2252 ///
2253 /// ```no_run
2254 /// use ipfs_api::{IpfsApi, IpfsClient};
2255 ///
2256 /// let client = IpfsClient::default();
2257 /// let res = client.stats_bw();
2258 /// ```
2259 ///
2260 async fn stats_bw(&self) -> Result<response::StatsBwResponse, Self::Error> {
2261 self.request(request::StatsBw, None).await
2262 }
2263
2264 /// Returns repo stats.
2265 ///
2266 /// ```no_run
2267 /// use ipfs_api::{IpfsApi, IpfsClient};
2268 ///
2269 /// let client = IpfsClient::default();
2270 /// let res = client.stats_repo();
2271 /// ```
2272 ///
2273 async fn stats_repo(&self) -> Result<response::StatsRepoResponse, Self::Error> {
2274 self.request(request::StatsRepo, None).await
2275 }
2276
2277 // TODO /swarm/addrs/listen
2278
2279 /// Return a list of local addresses.
2280 ///
2281 /// ```no_run
2282 /// use ipfs_api::{IpfsApi, IpfsClient};
2283 ///
2284 /// let client = IpfsClient::default();
2285 /// let res = client.swarm_addrs_local();
2286 /// ```
2287 ///
2288 async fn swarm_addrs_local(&self) -> Result<response::SwarmAddrsLocalResponse, Self::Error> {
2289 self.request(request::SwarmAddrsLocal, None).await
2290 }
2291
2292 /// Connect to a given peer
2293 ///
2294 /// ```no_run
2295 /// use ipfs_api::{IpfsApi, IpfsClient};
2296 ///
2297 /// let client = IpfsClient::default();
2298 /// let res = client.swarm_connect("/dns4/production-ipfs-cluster-us-east-1-node2.runfission.com/tcp/4003/wss/p2p/12D3KooWQ2hL9NschcJ1Suqa1TybJc2ZaacqoQMBT3ziFC7Ye2BZ");
2299 /// ```
2300 ///
2301 async fn swarm_connect(
2302 &self,
2303 peer: &str,
2304 ) -> Result<response::SwarmConnectResponse, Self::Error> {
2305 self.request(request::SwarmConnect { peer }, None).await
2306 }
2307
2308 // TODO /swarm/disconnect
2309
2310 // TODO /swarm/filters/add
2311
2312 // TODO /swarm/filters/rm
2313
2314 /// Return a list of peers with open connections.
2315 ///
2316 /// ```no_run
2317 /// use ipfs_api::{IpfsApi, IpfsClient};
2318 ///
2319 /// let client = IpfsClient::default();
2320 /// let res = client.swarm_peers();
2321 /// ```
2322 ///
2323 async fn swarm_peers(&self) -> Result<response::SwarmPeersResponse, Self::Error> {
2324 self.request(request::SwarmPeers, None).await
2325 }
2326
2327 /// Add a tar file to Ipfs.
2328 ///
2329 /// Note: `data` should already be a tar file. If it isn't the Api will return
2330 /// an error.
2331 ///
2332 /// ```no_run
2333 /// use ipfs_api::{IpfsApi, IpfsClient};
2334 /// use std::fs::File;
2335 ///
2336 /// let client = IpfsClient::default();
2337 /// let tar = File::open("/path/to/file.tar").unwrap();
2338 /// let res = client.tar_add(tar);
2339 /// ```
2340 ///
2341 async fn tar_add<R>(&self, data: R) -> Result<response::TarAddResponse, Self::Error>
2342 where
2343 R: 'static + Read + Send + Sync + Unpin,
2344 {
2345 let mut form = multipart::Form::default();
2346
2347 form.add_reader("file", data);
2348
2349 self.request(request::TarAdd, Some(form)).await
2350 }
2351
2352 /// Export a tar file from Ipfs.
2353 ///
2354 /// ```no_run
2355 /// use ipfs_api::{IpfsApi, IpfsClient};
2356 ///
2357 /// let client = IpfsClient::default();
2358 /// let res = client.tar_cat("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY");
2359 /// ```
2360 ///
2361 fn tar_cat(&self, path: &str) -> BoxStream<Bytes, Self::Error> {
2362 impl_stream_api_response! {
2363 (self, request::TarCat { path }, None) => request_stream_bytes
2364 }
2365 }
2366
2367 /// Returns information about the Ipfs server version.
2368 ///
2369 /// ```no_run
2370 /// use ipfs_api::{IpfsApi, IpfsClient};
2371 ///
2372 /// let client = IpfsClient::default();
2373 /// let res = client.version();
2374 /// ```
2375 ///
2376 async fn version(&self) -> Result<response::VersionResponse, Self::Error> {
2377 self.request(request::Version, None).await
2378 }
2379}
2380
2381impl<B> IpfsApi for B where B: Backend {}