Skip to content

Commit

Permalink
feat: impl pld support
Browse files Browse the repository at this point in the history
  • Loading branch information
dav1do committed May 20, 2024
1 parent f106593 commit 153a40c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ base64-url = { version = "2.0.2" }
ipld-core = { version = "0.4" }
serde_ipld_dagjson = { version = "0.2", default-features = false, optional = true }
serde_ipld_dagcbor = "0.6"
serde_json = "1"
serde = "1"
serde_derive = "1"
thiserror = "1"
Expand Down
14 changes: 13 additions & 1 deletion src/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,18 @@ impl TryFrom<Encoded> for JsonWebSignature {
type Error = Error;

fn try_from(value: Encoded) -> Result<Self, Self::Error> {
let link = Cid::try_from(value.payload.as_ref().ok_or(Error::NotJws)?.as_slice())?;
let payload = value.payload.as_ref().ok_or(Error::NotJws)?;

let (link, pld) = match serde_json::from_slice::<serde_json::Value>(payload.as_ref()) {
Ok(json) => {
let res = match crate::JsonPld(json).try_into().map_err(|_| Error::NotJws)? {
Ipld::Map(map) => map,
_ => return Err(Error::NotJws),
};
(None, Some(res))
}
Err(_) => (Some(Cid::try_from(payload.as_ref())?), None),
};
Ok(Self {
payload: value
.payload
Expand All @@ -104,6 +115,7 @@ impl TryFrom<Encoded> for JsonWebSignature {
.map(Signature::from)
.collect(),
link,
pld,
})
}
}
Expand Down
66 changes: 54 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ use std::collections::BTreeMap;
use ipld_core::{
cid::Cid,
codec::{Codec, Links},
ipld,
ipld::Ipld,
};
use serde_derive::Serialize;
Expand Down Expand Up @@ -152,22 +151,62 @@ impl Codec<Jose> for DagJsonCodec {
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct JsonWebSignature {
/// CID link from the payload.
pub link: Cid,

#[serde(skip_serializing_if = "Option::is_none")]
pub link: Option<Cid>,
/// The payload base64 url encoded.
pub payload: String,

#[serde(skip_serializing_if = "Option::is_none")]
/// The json payload with ipfs:// prefixed strings replaced with CIDs.
pub pld: Option<BTreeMap<String, Ipld>>,
/// The set of signatures.
pub signatures: Vec<Signature>,
}

impl<'a> From<&'a JsonWebSignature> for Ipld {
fn from(value: &'a JsonWebSignature) -> Self {
ipld!({
"payload": value.payload.to_owned(),
"signatures": value.signatures.iter().map(Ipld::from).collect::<Vec<Ipld>>(),
"link": value.link,
})
#[derive(Clone, Debug, PartialEq)]
/// Wrapper around a json value to convert ipfs:// prefixed strings to CIDs.
struct JsonPld(serde_json::Value);

impl TryFrom<JsonPld> for Ipld {
type Error = anyhow::Error;

fn try_from(value: JsonPld) -> Result<Self, Self::Error> {
// can we use a serde_ipld_* crate or something to handle most of this for for us?
match value.0 {
serde_json::Value::Null => Ok(Ipld::Null),
serde_json::Value::Bool(b) => Ok(Ipld::Bool(b)),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Ok(Ipld::Integer(i as i128))
} else if let Some(f) = n.as_f64() {
// should we reject NaN and infinities?
Ok(Ipld::Float(f))
} else {
anyhow::bail!("Invalid number. Should be unreachable")
}
}
serde_json::Value::String(s) => {
if let Some(str) = s.strip_prefix("ipfs://") {
let cid = Cid::try_from(str)?;
Ok(Ipld::Link(cid))
} else {
Ok(Ipld::String(s))
}
}
serde_json::Value::Array(arr) => {
let list = arr
.into_iter()
.map(|v| JsonPld(v).try_into())
.collect::<Result<Vec<_>, _>>()?;
Ok(Ipld::List(list))
}
serde_json::Value::Object(obj) => {
let map = obj
.into_iter()
.map(|(k, v)| JsonPld(v).try_into().map(|v| (k, v)))
.collect::<Result<BTreeMap<_, _>, _>>()?;
Ok(Ipld::Map(map))
}
}
}
}

Expand Down Expand Up @@ -356,6 +395,8 @@ impl<'a> From<&'a Recipient> for Ipld {
mod tests {
use std::collections::BTreeMap;

use ipld_core::ipld;

use super::*;

struct JwsFixture {
Expand Down Expand Up @@ -425,7 +466,7 @@ mod tests {
} = fixture_jws();
let (payload_b64, protected_b64, signature_b64) =
fixture_jws_base64(&payload, &protected, &signature);
let link = Cid::try_from(base64_url::decode(&payload_b64).unwrap()).unwrap();
let link = Some(Cid::try_from(base64_url::decode(&payload_b64).unwrap()).unwrap());
assert_roundtrip(
DagJoseCodec,
&JsonWebSignature {
Expand All @@ -439,6 +480,7 @@ mod tests {
signature: signature_b64,
}],
link,
pld: None,
},
&ipld!({
"payload": payload,
Expand Down

0 comments on commit 153a40c

Please sign in to comment.