diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2021-11-27 12:58:34 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2021-11-27 12:58:34 +0100 |
commit | fa3e9812524fb2322adb181b01852f61980b3fe0 (patch) | |
tree | 14a7cfbca7c342912913039b1c9cfc38b71057ab | |
parent | a2770c67fa450598d8420b3a4b5243969ecdd251 (diff) |
Implement putting in a text block and fetching it again
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/cid.rs | 1 | ||||
-rw-r--r-- | src/client.rs | 71 | ||||
-rw-r--r-- | src/types/datetime.rs | 2 | ||||
-rw-r--r-- | src/types/node.rs | 12 | ||||
-rw-r--r-- | src/types/payload.rs | 6 |
6 files changed, 86 insertions, 7 deletions
@@ -41,3 +41,4 @@ ed25519-dalek = "*" http = "0.2" serde = "1" serde_json = "1" +getset = "0.1" @@ -11,7 +11,6 @@ use anyhow::Result; #[serde(transparent)] pub struct Cid(String); -#[cfg(test)] impl AsRef<str> for Cid { fn as_ref(&self) -> &str { self.0.as_ref() diff --git a/src/client.rs b/src/client.rs index f984dfa..5523666 100644 --- a/src/client.rs +++ b/src/client.rs @@ -3,6 +3,7 @@ use std::io::Cursor; use anyhow::Result; use futures::FutureExt; use futures::TryFutureExt; +use futures::TryStreamExt; use ipfs_api_backend_hyper::IpfsApi; use crate::cid::Cid; @@ -85,6 +86,35 @@ impl Client { .map_err(anyhow::Error::from) .and_then(crate::ipfs_client::backend::response::DagPutResponse::try_to_cid) } + + pub async fn get_node(&self, cid: Cid) -> Result<Node> { + self.get_deserializeable::<Node>(cid).await + } + + pub async fn get_payload(&self, cid: Cid) -> Result<Payload> { + self.get_deserializeable::<Payload>(cid).await + } + + async fn get_deserializeable<D: serde::de::DeserializeOwned>(&self, cid: Cid) -> Result<D> { + let bytes = self.ipfs + .dag_get(cid.as_ref()) + .map_ok(|chunk| chunk.to_vec()) + .try_concat() + .await?; + + let s = String::from_utf8(bytes)?; + serde_json::from_str(&s).map_err(anyhow::Error::from) + } + + pub async fn get_content_text(&self, cid: Cid) -> Result<String> { + let bytes = self.ipfs + .cat(cid.as_ref()) + .map_ok(|chunk| chunk.to_vec()) + .try_concat() + .await?; + + String::from_utf8(bytes).map_err(anyhow::Error::from) + } } fn now() -> DateTime { @@ -128,4 +158,45 @@ mod tests { assert_eq!(cid.unwrap().as_ref(), "bafyreifqa7jqsazxvl53jb6sflzbk4nkv4j7b5jos6hlzh4fq55bjbvk3m"); } + #[tokio::test] + async fn test_post_text_node_roundtrip() { + use chrono::TimeZone; + + let _ = env_logger::try_init(); + let ipfs = IpfsClient::from_str("http://localhost:5001").unwrap(); + let config = Config::default(); + let client = Client::new(ipfs, config); + + let datetime: crate::types::DateTime = chrono::prelude::Utc.ymd(2021, 11, 27) + .and_hms(12, 30, 0) + .into(); + + let text = "text-roundtrip"; + + let cid = client.post_text_node_with_datetime(Vec::new(), String::from(text), datetime.clone()).await; + assert!(cid.is_ok()); + let cid = cid.unwrap(); + assert_eq!(cid.as_ref(), "bafyreibenqhh2fqf33mdvm4b4k7kpymnyhuduebwdmaxraxttld7i2bbbi"); + + let node = client.get_node(cid).await; + assert!(node.is_ok()); + let node = node.unwrap(); + + assert_eq!(*node.version(), crate::consts::protocol_version()); + assert!(node.parents().is_empty()); + + let payload = client.get_payload(node.payload().clone()).await; + assert!(payload.is_ok()); + let payload = payload.unwrap(); + + assert_eq!(payload.mime(), mime::TEXT_PLAIN_UTF_8.as_ref()); + assert_eq!(payload.timestamp(), &datetime); + + let content = client.get_content_text(payload.content().clone()).await; + assert!(content.is_ok()); + let content = content.unwrap(); + + assert_eq!(content, text); + } + } diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 9034c26..6735731 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -1,6 +1,6 @@ use anyhow::Error; -#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[serde(transparent)] pub struct DateTime(chrono::DateTime<chrono::Utc>); diff --git a/src/types/node.rs b/src/types/node.rs index 60b10d1..278fa7f 100644 --- a/src/types/node.rs +++ b/src/types/node.rs @@ -1,12 +1,16 @@ -#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, getset::Getters)] pub struct Node { /// Version - v: String, + #[serde(rename = "v")] + #[getset(get = "pub")] + version: String, /// Parent Nodes, identified by cid + #[getset(get = "pub")] parents: Vec<crate::cid::Cid>, /// The actual payload of the node, which is stored in another document identified by this cid + #[getset(get = "pub")] payload: crate::cid::Cid, } @@ -19,7 +23,7 @@ impl daglib::Node for Node { } impl Node { - pub fn new(v: String, parents: Vec<crate::cid::Cid>, payload: crate::cid::Cid) -> Self { - Self { v, parents, payload } + pub fn new(version: String, parents: Vec<crate::cid::Cid>, payload: crate::cid::Cid) -> Self { + Self { version, parents, payload } } } diff --git a/src/types/payload.rs b/src/types/payload.rs index 5b6cfb1..e6ddb0f 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -1,12 +1,16 @@ use crate::types::DateTime; -#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, getset::Getters)] pub struct Payload { // TODO: Make this a mime::Mime, but as this type does not impl Serialize/Deserialize, we // cannot do this trivially yet + #[getset(get = "pub")] mime: String, + #[getset(get = "pub")] timestamp: DateTime, + + #[getset(get = "pub")] content: crate::cid::Cid, } |