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 {}