Skip to content

Commit

Permalink
add Data trait + JsonData
Browse files Browse the repository at this point in the history
  • Loading branch information
kayhhh committed Dec 19, 2023
1 parent 5d02398 commit b87392c
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 31 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dwn-server/tests/messages.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use dwn::{
data::JsonData,
features::FeatureDetection,
request::{
media_types::{Application, MediaType},
Expand Down Expand Up @@ -35,12 +36,11 @@ async fn send_post(data: RequestBody, port: u16) -> Response {
}

fn empty_message() -> Message {
let builder = MessageBuilder {
let builder = MessageBuilder::<JsonData> {
data: None,
descriptor: DescriptorBuilder {
method: Method::FeatureDetectionRead,
interface: Interface::FeatureDetection,
data_format: None,
},
};

Expand Down
1 change: 1 addition & 0 deletions dwn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cid = "0.11.0"
iana-media-types = "0.1.2"
libipld-cbor = "0.16.0"
libipld-core = "0.16.0"
libipld-json = "0.16.0"
libipld-pb = "0.16.0"
multihash-codetable = { version = "0.1.1", features = ["digest", "sha2"] }
serde = { version = "1.0.193", features = ["derive"] }
Expand Down
60 changes: 60 additions & 0 deletions dwn/src/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use base64::Engine;
use iana_media_types::Application;
use libipld_core::{codec::Codec, ipld::Ipld};
use libipld_json::DagJsonCodec;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::request::DataFormat;

pub trait Data {
/// Returns the data as a base64url-encoded string.
fn to_base64url(&self) -> String;
/// Returns the data as an IPLD object.
fn to_ipld(&self) -> Ipld;
/// Returns the data format of this data.
fn data_format(&self) -> DataFormat;
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JsonData(Value);

impl Data for JsonData {
fn to_base64url(&self) -> String {
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(self.0.to_string())
}

fn to_ipld(&self) -> Ipld {
let json = self.0.to_string();
let bytes = json.as_bytes();
DagJsonCodec.decode(bytes).expect("Failed to decode JSON")
}

fn data_format(&self) -> DataFormat {
DataFormat::MediaType(Application::Json.into())
}
}

#[cfg(test)]
mod tests {
use super::{Data, JsonData};
use libipld_core::codec::Codec;

#[test]
fn test_json_data() {
let data = JsonData(serde_json::json!({
"foo": "bar",
}));

assert_eq!(data.to_base64url(), "eyJmb28iOiJiYXIifQ");
assert_eq!(data.data_format().to_string(), "\"application/json\"");

let ipld = data.to_ipld();
let encoded = libipld_json::DagJsonCodec
.encode(&ipld)
.expect("Failed to encode IPLD");
let encoded_string = String::from_utf8(encoded).expect("Failed to convert to string");

assert_eq!(encoded_string, "{\"foo\":\"bar\"}");
}
}
1 change: 1 addition & 0 deletions dwn/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod data;
pub mod features;
pub mod request;
pub mod response;
Expand Down
44 changes: 16 additions & 28 deletions dwn/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use base64::Engine;
pub use iana_media_types as media_types;
use libipld_cbor::DagCborCodec;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt::Display;

use crate::util::cid_from_bytes;
use crate::{data::Data, util::cid_from_bytes};

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RequestBody {
Expand All @@ -21,12 +19,12 @@ pub struct Message {
pub descriptor: Descriptor,
}

pub struct MessageBuilder {
pub data: Option<Data>,
pub struct MessageBuilder<T: Data> {
pub data: Option<T>,
pub descriptor: DescriptorBuilder,
}

impl MessageBuilder {
impl<T: Data> MessageBuilder<T> {
pub fn build(&self) -> Result<Message, Box<dyn std::error::Error>> {
let data = self.data.as_ref().map(|d| d.to_base64url());
let descriptor = self.descriptor.build(self.data.as_ref())?;
Expand All @@ -47,22 +45,6 @@ impl MessageBuilder {
}
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Data {
Json(Value),
}

impl Data {
pub fn to_base64url(&self) -> String {
match self {
Data::Json(value) => {
base64::engine::general_purpose::URL_SAFE.encode(value.to_string())
}
}
}
}

#[derive(Serialize)]
pub struct RecordIdGenerator {
#[serde(rename = "descriptorCid")]
Expand Down Expand Up @@ -130,7 +112,7 @@ impl Display for Method {
}
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum DataFormat {
/// JSON Web Token formatted Verifiable Credential
Expand All @@ -157,20 +139,26 @@ impl From<&DataFormat> for String {
pub struct DescriptorBuilder {
pub interface: Interface,
pub method: Method,
pub data_format: Option<DataFormat>,
}

impl DescriptorBuilder {
pub fn build(&self, data: Option<&Data>) -> Result<Descriptor, Box<dyn std::error::Error>> {
let data_cid = data.map(|_d| {
"".to_string() // TODO: Generate CID
pub fn build<T: Data>(
&self,
data: Option<&T>,
) -> Result<Descriptor, Box<dyn std::error::Error>> {
let data_cid = data.map(|d| {
// TODO: Generate CID
let pb = d.to_ipld();
"TODO".to_string()
});

let data_format = data.map(|d| d.data_format());

Ok(Descriptor {
interface: self.interface.clone(),
method: self.method.clone(),
data_cid,
data_format: self.data_format.clone(),
data_format,
})
}
}
1 change: 0 additions & 1 deletion dwn/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use cid::Cid;

use multihash_codetable::{Code, MultihashDigest};

pub fn cid_from_bytes(codec: u64, bytes: &[u8]) -> Cid {
Expand Down

0 comments on commit b87392c

Please sign in to comment.