Skip to content

Commit

Permalink
Added display impls and started filling out DidKey struct
Browse files Browse the repository at this point in the history
  • Loading branch information
TheButlah committed May 14, 2024
1 parent f2bad23 commit 0957e1e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 21 deletions.
99 changes: 98 additions & 1 deletion crates/did-simple/src/methods/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,104 @@
//!
//! [did:key]: https://w3c-ccg.github.io/did-method-key/

use std::fmt::Display;

use crate::{
uri::{DidMethod, DidUri},
utf8bytes::Utf8Bytes,
};

/// An implementation of the `did:key` method. See the [module](self) docs for more
/// info.
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct DidKey;
pub struct DidKey {
/// The string representation of the DID.
s: Utf8Bytes,
/// The substring for method-specific-id. This is a range index into `s`.
method_specific_id: std::ops::RangeFrom<usize>,
}

impl DidKey {
const PREFIX: &'static str = "did:key:";

/// Gets the buffer representing the uri as a str.
pub fn as_str(&self) -> &str {
self.s.as_str()
}

/// Gets the buffer representing the uri as a byte slice.
pub fn as_slice(&self) -> &[u8] {
self.s.as_slice()
}

/// Gets the buffer representing the uri as a reference counted slice that
/// is guaranteed to be utf8.
pub fn as_utf8_bytes(&self) -> &Utf8Bytes {
&self.s
}
}

impl TryFrom<DidUri> for DidKey {
type Error = FromUriError;

fn try_from(value: DidUri) -> Result<Self, Self::Error> {
let m = value.method();
if m != DidMethod::Key {
return Err(FromUriError::WrongMethod(m));
}
debug_assert_eq!(
value.as_slice().len() - value.method_specific_id().as_slice().len(),
Self::PREFIX.len(),
"sanity check that prefix has expected length"
);

Ok(Self {
s: value.as_utf8_bytes().clone(),
method_specific_id: (Self::PREFIX.len()..),
})
}
}

#[derive(thiserror::Error, Debug)]
pub enum FromUriError {
#[error("Expected \"key\" method but got {0:?}")]
WrongMethod(DidMethod),
}

impl Display for DidKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().fmt(f)
}
}

#[cfg(test)]
mod test {
use super::*;

use eyre::WrapErr;
use std::str::FromStr;

fn common_examples() -> Vec<DidKey> {
let p = DidKey::PREFIX;
let make_example = |s| DidKey {
s: format!("{p}{s}").into(),
method_specific_id: (p.len()..),
};
["deadbeef123", "yeet"]
.into_iter()
.map(make_example)
.collect()
}

#[test]
fn test_try_from_uri() -> eyre::Result<()> {
for example in common_examples() {
let uri = DidUri::from_str(example.as_str())
.wrap_err_with(|| format!("failed to parse DidUri from {example}"))?;
let key_from_uri = DidKey::try_from(uri.clone())
.wrap_err_with(|| format!("failed to parse DidKey from {uri}"))?;
assert_eq!(uri.as_str(), key_from_uri.as_str());
}
Ok(())
}
}
46 changes: 26 additions & 20 deletions crates/did-simple/src/uri.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::str::FromStr;

use bytes::Bytes;
use std::{fmt::Display, str::FromStr};

use crate::utf8bytes::Utf8Bytes;

Expand Down Expand Up @@ -40,7 +38,7 @@ impl MethodSpecificId<'_> {
}
}

#[derive(Debug, Eq, PartialEq, Hash)]
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct DidUri {
method: DidMethod,
/// The string representation of the DID.
Expand All @@ -60,16 +58,12 @@ impl DidUri {
self.s.as_slice()
}

/// Gets the buffer representing the uri as a byte slice that is guaranteed to be utf8.
pub fn utf8_bytes(&self) -> &Utf8Bytes {
/// Gets the buffer representing the uri as a reference counted slice that
/// is guaranteed to be utf8.
pub fn as_utf8_bytes(&self) -> &Utf8Bytes {
&self.s
}

/// Gets the buffer representing the uri as bytes.
pub fn bytes(&self) -> &Bytes {
self.s.bytes()
}

/// The method of the did.
pub fn method(&self) -> DidMethod {
self.method
Expand All @@ -79,10 +73,6 @@ impl DidUri {
pub fn method_specific_id(&self) -> MethodSpecificId {
MethodSpecificId(self)
}

pub fn into_inner(self) -> Utf8Bytes {
self.s
}
}

impl FromStr for DidUri {
Expand Down Expand Up @@ -135,19 +125,28 @@ pub enum ParseError {
UnknownMethod,
}

impl Display for DidUri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().fmt(f)
}
}

#[cfg(test)]
mod test {
use super::*;
use eyre::{Result, WrapErr};

#[test]
fn test_parse() -> Result<()> {
let test_cases = [DidUri {
fn common_test_cases() -> Vec<DidUri> {
vec![DidUri {
method: DidMethod::Key,
s: String::from("did:key:123456").into(),
method_specific_id: (8..),
}];
for expected in test_cases {
}]
}

#[test]
fn test_parse() -> Result<()> {
for expected in common_test_cases() {
let s = expected.s.as_str().to_owned();
let from_str = DidUri::from_str(&s).wrap_err("failed to from_str")?;
let try_from = DidUri::try_from(s).wrap_err("failed to try_from")?;
Expand All @@ -156,4 +155,11 @@ mod test {
}
Ok(())
}

#[test]
fn test_display() {
for example in common_test_cases() {
assert_eq!(example.as_str(), format!("{example}"));
}
}
}

0 comments on commit 0957e1e

Please sign in to comment.