Skip to content

Commit

Permalink
Merge pull request ucan-wg#3 from fission-codes/matheus23/expose-serde
Browse files Browse the repository at this point in the history
feat: Implement Serialize/Deserialize for UCAN
  • Loading branch information
QuinnWilton committed Oct 23, 2023
2 parents 16e5565 + 7da838e commit f3e3bff
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ where
}

/// Set the issuer of the UCAN
pub fn issued_by<S: AsRef<str>>(mut self, issuer: S) -> Self {
pub fn issued_by(mut self, issuer: impl AsRef<str>) -> Self {
self.issuer = Some(issuer.as_ref().to_string());
self
}

/// Set the audience of the UCAN
pub fn for_audience<S: AsRef<str>>(mut self, audience: S) -> Self {
pub fn for_audience(mut self, audience: impl AsRef<str>) -> Self {
self.audience = Some(audience.as_ref().to_string());
self
}

/// Set the nonce of the UCAN
pub fn with_nonce<S: AsRef<str>>(mut self, nonce: S) -> Self {
pub fn with_nonce(mut self, nonce: impl AsRef<str>) -> Self {
self.nonce = Some(nonce.as_ref().to_string());
self
}
Expand Down
2 changes: 1 addition & 1 deletion src/did_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl DidVerifierMap {
self.map
.get(method)
.ok_or_else(|| Error::VerifyingError {
msg: format!("Unrecognized DID method, {}", method).to_string(),
msg: format!("Unrecognized DID method, {}", method),
})?
.verify(identifier, payload, signature)
.map_err(|e| Error::VerifyingError { msg: e.to_string() })
Expand Down
43 changes: 41 additions & 2 deletions src/semantics/caveat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fmt;
use downcast_rs::{impl_downcast, Downcast};
use dyn_clone::{clone_trait_object, DynClone};
use erased_serde::serialize_trait_object;
use serde::{Deserialize, Serialize};
use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};

/// A caveat defined as part of a semantics
pub trait Caveat: Send + Sync + DynClone + Downcast + erased_serde::Serialize + 'static {
Expand All @@ -27,7 +27,7 @@ impl fmt::Debug for dyn Caveat {
}

/// A caveat that is always valid
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct EmptyCaveat;

impl Caveat for EmptyCaveat {
Expand All @@ -53,3 +53,42 @@ impl Caveat for Box<dyn Caveat> {
(**self).is_valid_attenuation(other)
}
}

impl<'de> Deserialize<'de> for EmptyCaveat {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct NoFieldsVisitor;

impl<'de> Visitor<'de> for NoFieldsVisitor {
type Value = EmptyCaveat;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an empty object")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
if let Some(field) = map.next_key()? {
return Err(serde::de::Error::unknown_field(field, &[]));
}

Ok(EmptyCaveat)
}
}

deserializer.deserialize_map(NoFieldsVisitor)
}
}

impl Serialize for EmptyCaveat {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_map(Some(0))?.end()
}
}
35 changes: 33 additions & 2 deletions src/ucan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
error::Error,
semantics::{ability::Ability, resource::Resource},
store::Store,
CidString, DefaultFact, Did,
CidString, DefaultFact,
};
use cid::{
multihash::{self, MultihashDigest},
Expand Down Expand Up @@ -138,7 +138,7 @@ where
/// perform the ability against the resource
pub fn capabilities_for<R, A, S>(
&self,
issuer: Did,
issuer: impl AsRef<str>,
resource: R,
ability: A,
at_time: u64,
Expand All @@ -150,6 +150,8 @@ where
A: Ability,
S: Store<RawCodec, Error = anyhow::Error>,
{
let issuer = issuer.as_ref();

let mut capabilities = vec![];
let mut proof_queue: VecDeque<(Ucan<F, C>, Capability, Capability)> = VecDeque::default();

Expand Down Expand Up @@ -462,6 +464,35 @@ where
}
}

impl<'de, F, C> Deserialize<'de> for Ucan<F, C>
where
C: CapabilityParser,
F: DeserializeOwned,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ucan::<F, C>::from_str(&String::deserialize(deserializer)?)
.map_err(|e| serde::de::Error::custom(e.to_string()))
}
}

impl<F, C> Serialize for Ucan<F, C>
where
C: CapabilityParser,
F: Clone + DeserializeOwned,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.encode()
.map_err(|e| serde::ser::Error::custom(e.to_string()))?
.serialize(serializer)
}
}

fn deserialize_required_nullable<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: Deserialize<'de>,
Expand Down

0 comments on commit f3e3bff

Please sign in to comment.