summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerris Tseng <ferristseng@fastmail.fm>2020-07-18 22:34:29 -0400
committerGitHub <noreply@github.com>2020-07-18 22:34:29 -0400
commita404a4e8ef2dca29153945ec20e5e0dff73cde66 (patch)
tree80a0f97d682496ab91e57c8873704eae66e24c56
parentec9c5269467537db4916eab6d5163f6e8b92fbaa (diff)
parenta3ad2e6bd9b8ed05587ea990c2136953ad2fd50f (diff)
Merge pull request #54 from jcaesar/master
Add lots of missing parameters on ipfs files
-rw-r--r--ipfs-api/src/client/internal.rs314
-rw-r--r--ipfs-api/src/request/files.rs111
-rw-r--r--ipfs-api/src/response/files.rs7
3 files changed, 399 insertions, 33 deletions
diff --git a/ipfs-api/src/client/internal.rs b/ipfs-api/src/client/internal.rs
index 475ec17..0817ada 100644
--- a/ipfs-api/src/client/internal.rs
+++ b/ipfs-api/src/client/internal.rs
@@ -39,6 +39,8 @@ use std::{
};
use tokio_util::codec::{Decoder, FramedRead};
+fn default<T: Default>() -> T { Default::default() }
+
const FILE_DESCRIPTOR_LIMIT: usize = 127;
#[cfg(feature = "actix")]
@@ -1122,10 +1124,27 @@ impl IpfsClient {
path: &str,
dest: &str,
) -> Result<response::FilesCpResponse, Error> {
- self.request_empty(request::FilesCp { path, dest }, None)
+ self.files_cp_with_options(request::FilesCp { path, dest, .. default() })
.await
}
+ /// Copy files into MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// let res = client.files_cp("/path/to/file", "/dest");
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_cp_with_options(
+ &self,
+ options: request::FilesCp<'_>,
+ ) -> Result<response::FilesCpResponse, Error> {
+ self.request_empty(options, None).await
+ }
+
/// Flush a path's data to disk.
///
/// ```no_run
@@ -1156,7 +1175,36 @@ impl IpfsClient {
///
#[inline]
pub async fn files_ls(&self, path: Option<&str>) -> Result<response::FilesLsResponse, Error> {
- self.request(request::FilesLs { path }, None).await
+ self.files_ls_with_options(request::FilesLs { path: path, .. default() }).await
+ }
+
+ /// List directories in MFS..
+ ///
+ /// ```no_run
+ /// let client = ipfs_api::IpfsClient::default();
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesLs::builder()
+ /// // .path("/") // defaults to /
+ /// .unsorted(false)
+ /// .long(true)
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesLs {
+ /// path: None, // defaults to /
+ /// unsorted: Some(false),
+ /// long: Some(true),
+ /// };
+ /// let res = client.files_ls_with_options(req);
+ /// ```
+ ///
+ /// Defaults to `-U`, so the output is unsorted.
+ ///
+ #[inline]
+ pub async fn files_ls_with_options(
+ &self,
+ options: request::FilesLs<'_>
+ ) -> Result<response::FilesLsResponse, Error> {
+ self.request(options, None).await
}
/// Make directories in MFS.
@@ -1175,8 +1223,37 @@ impl IpfsClient {
path: &str,
parents: bool,
) -> Result<response::FilesMkdirResponse, Error> {
- self.request_empty(request::FilesMkdir { path, parents }, None)
- .await
+ self.files_mkdir_with_options(request::FilesMkdir { path, parents: Some(parents), .. default() }).await
+ }
+
+ /// Make directories in MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesMkdir::builder()
+ /// .path("/test/nested/dir")
+ /// .parents(true)
+ /// .flush(false)
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesMkdir {
+ /// path: "/test/nested/dir",
+ /// parents: Some(true),
+ /// flush: Some(false),
+ /// .. Default::default()
+ /// };
+ /// let res = client.files_mkdir_with_options(req);
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_mkdir_with_options(
+ &self,
+ options: request::FilesMkdir<'_>
+ ) -> Result<response::FilesMkdirResponse, Error> {
+ self.request_empty(options, None).await
}
/// Copy files into MFS.
@@ -1194,7 +1271,31 @@ impl IpfsClient {
path: &str,
dest: &str,
) -> Result<response::FilesMvResponse, Error> {
- self.request_empty(request::FilesMv { path, dest }, None)
+ self.files_mv_with_options(request::FilesMv { path, dest, .. default() })
+ .await
+ }
+
+ /// Copy files into MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// let res = client.files_mv_with_options(
+ /// ipfs_api::request::FilesMv {
+ /// path: "/test/tmp.json",
+ /// dest: "/test/file.json",
+ /// flush: Some(false),
+ /// }
+ /// );
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_mv_with_options(
+ &self,
+ options: request::FilesMv<'_>,
+ ) -> Result<response::FilesMvResponse, Error> {
+ self.request_empty(options, None)
.await
}
@@ -1209,9 +1310,33 @@ impl IpfsClient {
///
#[inline]
pub fn files_read(&self, path: &str) -> impl Stream<Item = Result<Bytes, Error>> {
- impl_stream_api_response! {
- (self, request::FilesRead { path }, None) => request_stream_bytes
- }
+ self.files_read_with_options(request::FilesRead { path, .. request::FilesRead::default() })
+ }
+
+ /// Read a file in MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesRead::builder()
+ /// .path("/test/file.json")
+ /// .offset(1024)
+ /// .count(8)
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesRead {
+ /// path: "/test/file.json",
+ /// offset: Some(1024),
+ /// count: Some(8),
+ /// };
+ /// let res = client.files_read_with_options(req);
+ /// ```
+ ///
+ #[inline]
+ pub fn files_read_with_options(&self, options: request::FilesRead) -> impl Stream<Item = Result<Bytes, Error>> {
+ impl_stream_api_response! { (self, options, None) => request_stream_bytes }
}
/// Remove a file in MFS.
@@ -1230,11 +1355,39 @@ impl IpfsClient {
path: &str,
recursive: bool,
) -> Result<response::FilesRmResponse, Error> {
- self.request_empty(request::FilesRm { path, recursive }, None)
- .await
+ self.files_rm_with_options(request::FilesRm { path, recursive: Some(recursive), .. default() }).await
+ }
+
+ /// Remove a file in MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesRm::builder()
+ /// .path("/test/somefile.json")
+ /// .recursive(false)
+ /// .flush(false)
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesRm {
+ /// path: "/test/somefile.json",
+ /// recursive: Some(false),
+ /// flush: Some(false),
+ /// };
+ /// let res = client.files_rm_with_options(req);
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_rm_with_options(
+ &self,
+ options: request::FilesRm<'_>
+ ) -> Result<response::FilesRmResponse, Error> {
+ self.request_empty(options, None).await
}
- /// Display a file's status in MDFS.
+ /// Display a file's status in MFS.
///
/// ```no_run
/// use ipfs_api::IpfsClient;
@@ -1245,7 +1398,29 @@ impl IpfsClient {
///
#[inline]
pub async fn files_stat(&self, path: &str) -> Result<response::FilesStatResponse, Error> {
- self.request(request::FilesStat { path }, None).await
+ self.files_stat_with_options(request::FilesStat { path, .. default() }).await
+ }
+
+ /// Display a file's status in MFS.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ ///
+ /// let client = IpfsClient::default();
+ /// let res = client.files_stat_with_options(
+ /// ipfs_api::request::FilesStat {
+ /// path: "/test/dir/",
+ /// with_local: Some(true),
+ /// }
+ /// );
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_stat_with_options(
+ &self,
+ options: request::FilesStat<'_>
+ ) -> Result<response::FilesStatResponse, Error> {
+ self.request(options, None).await
}
/// Write to a mutable file in the filesystem.
@@ -1270,19 +1445,116 @@ impl IpfsClient {
where
R: 'static + Read + Send + Sync,
{
+ let options = request::FilesWrite {
+ path,
+ create: Some(create),
+ truncate: Some(truncate),
+ .. request::FilesWrite::default()
+ };
+ self.files_write_with_options(options, data).await
+ }
+
+ /// Write to a mutable file in the filesystem.
+ ///
+ /// ```no_run
+ /// let client = ipfs_api::IpfsClient::default();
+ /// let data = std::io::Cursor::new((1..128).collect::<Vec<u8>>());
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesWrite::builder()
+ /// .path("/test/outfile.bin")
+ /// .create(false)
+ /// .truncate(false)
+ /// .offset(1 << 20)
+ /// .flush(false)
+ /// // see FilesWriteBuilder for the full set of options
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesWrite {
+ /// path: "/test/outfile.bin",
+ /// create: Some(false),
+ /// truncate: Some(false),
+ /// offset: Some(1 << 20),
+ /// flush: Some(false),
+ /// .. Default::default()
+ /// };
+ /// let res = client.files_write_with_options(req, data);
+ /// ```
+ ///
+ #[inline]
+ pub async fn files_write_with_options<R>(
+ &self,
+ options: request::FilesWrite<'_>,
+ data: R,
+ ) -> Result<response::FilesWriteResponse, Error>
+ where
+ R: 'static + Read + Send + Sync,
+ {
let mut form = multipart::Form::default();
form.add_reader("data", data);
- self.request_empty(
- request::FilesWrite {
- path,
- create,
- truncate,
- },
- Some(form),
- )
- .await
+ self.request_empty(options, Some(form)).await
+ }
+
+ /// Change the cid version or hash function of the root node of a given path.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ /// use std::fs::File;
+ ///
+ /// let client = IpfsClient::default();
+ /// let res = client.files_chcid("/test/", 1);
+ /// ```
+ ///
+ /// Not specifying a byte `count` writes the entire input.
+ ///
+ #[inline]
+ pub async fn files_chcid(
+ &self,
+ path: &str,
+ cid_version: i32,
+ ) -> Result<response::FilesChcidResponse, Error>
+ {
+ self.request_empty(request::FilesChcid {
+ path: Some(path),
+ cid_version: Some(cid_version),
+ .. default()
+ }, None).await
+ }
+
+ /// Change the cid version or hash function of the root node of a given path.
+ ///
+ /// ```no_run
+ /// use ipfs_api::IpfsClient;
+ /// use std::fs::File;
+ ///
+ /// let client = IpfsClient::default();
+ /// #[cfg(feature = "builder")]
+ /// let req = ipfs_api::request::FilesChcid::builder()
+ /// .path("/test/")
+ /// .cid_version(1)
+ /// .hash("sha3-512")
+ /// .flush(true)
+ /// .build();
+ /// #[cfg(not(feature = "builder"))]
+ /// let req = ipfs_api::request::FilesChcid {
+ /// path: Some("/test/"),
+ /// cid_version: Some(1),
+ /// hash: Some("sha3-512"),
+ /// flush: Some(false),
+ /// };
+ /// let res = client.files_chcid_with_options(req);
+ /// ```
+ ///
+ /// Not specifying a byte `count` writes the entire input.
+ ///
+ #[inline]
+ pub async fn files_chcid_with_options(
+ &self,
+ options: request::FilesChcid<'_>
+ ) -> Result<response::FilesChcidResponse, Error>
+ {
+ self.request_empty(options, None).await
}
/// List blocks that are both in the filestore and standard block storage.
diff --git a/ipfs-api/src/request/files.rs b/ipfs-api/src/request/files.rs
index 3ec4186..498faa9 100644
--- a/ipfs-api/src/request/files.rs
+++ b/ipfs-api/src/request/files.rs
@@ -9,13 +9,15 @@
use crate::request::ApiRequest;
use crate::serde::Serialize;
-#[derive(Serialize)]
+#[derive(Serialize, Default)]
pub struct FilesCp<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
#[serde(rename = "arg")]
pub dest: &'a str,
+
+ pub flush: Option<bool>,
}
impl<'a> ApiRequest for FilesCp<'a> {
@@ -32,83 +34,168 @@ impl<'a> ApiRequest for FilesFlush<'a> {
const PATH: &'static str = "/files/flush";
}
-#[derive(Serialize)]
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
pub struct FilesLs<'a> {
#[serde(rename = "arg")]
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
pub path: Option<&'a str>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub long: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ #[serde(rename = "U")]
+ pub unsorted: Option<bool>,
}
impl<'a> ApiRequest for FilesLs<'a> {
const PATH: &'static str = "/files/ls";
}
-#[derive(Serialize)]
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
+#[serde(rename_all = "kebab-case")]
pub struct FilesMkdir<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
- pub parents: bool,
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub parents: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub hash: Option<&'a str>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub cid_version: Option<i32>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub flush: Option<bool>,
}
impl<'a> ApiRequest for FilesMkdir<'a> {
const PATH: &'static str = "/files/mkdir";
}
-#[derive(Serialize)]
+#[derive(Serialize, Default)]
pub struct FilesMv<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
#[serde(rename = "arg")]
pub dest: &'a str,
+
+ pub flush: Option<bool>,
}
impl<'a> ApiRequest for FilesMv<'a> {
const PATH: &'static str = "/files/mv";
}
-#[derive(Serialize)]
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
pub struct FilesRead<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub offset: Option<i64>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub count: Option<i64>,
}
impl<'a> ApiRequest for FilesRead<'a> {
const PATH: &'static str = "/files/read";
}
-#[derive(Serialize)]
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
pub struct FilesRm<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
- pub recursive: bool,
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub recursive: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub flush: Option<bool>,
}
impl<'a> ApiRequest for FilesRm<'a> {
const PATH: &'static str = "/files/rm";
}
-#[derive(Serialize)]
+#[derive(Serialize, Default)]
+#[serde(rename_all = "kebab-case")]
pub struct FilesStat<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
+
+ pub with_local: Option<bool>,
}
impl<'a> ApiRequest for FilesStat<'a> {
const PATH: &'static str = "/files/stat";
}
-#[derive(Serialize)]
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
+#[serde(rename_all = "kebab-case")]
pub struct FilesWrite<'a> {
#[serde(rename = "arg")]
pub path: &'a str,
- pub create: bool,
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub create: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub truncate: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub parents: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub offset: Option<i64>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub count: Option<i64>,
- pub truncate: bool,
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub raw_leaves: Option<bool>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub hash: Option<&'a str>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub cid_version: Option<i32>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub flush: Option<bool>,
}
impl<'a> ApiRequest for FilesWrite<'a> {
const PATH: &'static str = "/files/write";
}
+
+#[cfg_attr(feature = "builder", derive(TypedBuilder))]
+#[derive(Serialize, Default)]
+#[serde(rename_all = "kebab-case")]
+pub struct FilesChcid<'a> {
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ #[serde(rename = "arg")]
+ pub path: Option<&'a str>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub hash: Option<&'a str>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub cid_version: Option<i32>,
+
+ #[cfg_attr(feature = "builder", builder(default, setter(strip_option)))]
+ pub flush: Option<bool>,
+}
+
+impl<'a> ApiRequest for FilesChcid<'a> {
+ const PATH: &'static str = "/files/chcid";
+}
diff --git a/ipfs-api/src/response/files.rs b/ipfs-api/src/response/files.rs
index 069ba32..f27be1f 100644
--- a/ipfs-api/src/response/files.rs
+++ b/ipfs-api/src/response/files.rs
@@ -50,10 +50,17 @@ pub struct FilesStatResponse {
#[serde(rename = "Type")]
pub typ: String,
+
+ #[serde(default)]
+ pub size_local: Option<u64>,
+ #[serde(default)]
+ pub local: Option<bool>,
}
pub type FilesWriteResponse = ();
+pub type FilesChcidResponse = ();
+
#[cfg(test)]
mod tests {
deserialize_test!(v0_files_ls_0, FilesLsResponse);