-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Started work on did-simple and did-chain
- Loading branch information
Showing
11 changed files
with
452 additions
and
8 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "did-chain" | ||
version.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
description = "A chain of Decentralized Identifiers" | ||
|
||
[dependencies] | ||
did-simple.path = "../did-simple" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use did_simple::{methods::key::DidKey, methods::DidDyn}; | ||
|
||
/// This is like an account UUID, it provides a unique identifier for the | ||
/// account. Changing it is impossible. | ||
#[derive(Debug)] | ||
pub struct DidRoot(DidKey); | ||
|
||
#[derive(Debug)] | ||
pub struct DidChain { | ||
pub root: DidRoot, | ||
pub chain: Vec<DidDyn>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "did-simple" | ||
version.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
description = "Dead simple DIDs" | ||
|
||
[dependencies] | ||
thiserror = "1.0.60" | ||
bytes = "1.6.0" | ||
|
||
[dev-dependencies] | ||
eyre = "0.6.12" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![forbid(unsafe_code)] | ||
|
||
use std::str::FromStr; | ||
|
||
pub mod methods; | ||
pub mod uri; | ||
pub mod utf8bytes; | ||
|
||
pub trait Did: FromStr { | ||
fn uri(&self) -> self::uri::DidUri; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
//! An implementation of the [did:key] method. | ||
//! | ||
//! [did:key]: https://w3c-ccg.github.io/did-method-key/ | ||
/// An implementation of the `did:key` method. See the [module](self) docs for more | ||
/// info. | ||
#[derive(Debug, Eq, PartialEq, Hash, Clone)] | ||
pub struct DidKey; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
pub mod key; | ||
pub mod web; | ||
|
||
/// Dynamically typed did method. | ||
#[derive(Debug, Eq, PartialEq, Hash, Clone)] | ||
#[non_exhaustive] | ||
pub enum DidDyn { | ||
Key(self::key::DidKey), | ||
Web(self::web::DidWeb), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
//! An implementation of the [did:web] method. | ||
//! | ||
//! [did:web]: https://w3c-ccg.github.io/did-method-web | ||
/// An implementation of the `did:web` method. See the [module](self) docs for more | ||
/// info. | ||
#[derive(Debug, Eq, PartialEq, Hash, Clone)] | ||
pub struct DidWeb; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
use std::str::FromStr; | ||
|
||
use bytes::Bytes; | ||
|
||
use crate::utf8bytes::Utf8Bytes; | ||
|
||
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)] | ||
pub enum DidMethod { | ||
Key, | ||
Web, | ||
} | ||
|
||
impl FromStr for DidMethod { | ||
type Err = ParseError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
Ok(match s { | ||
"key" => Self::Key, | ||
"web" => Self::Web, | ||
"" => return Err(ParseError::MissingMethod), | ||
_ => return Err(ParseError::UnknownMethod), | ||
}) | ||
} | ||
} | ||
|
||
/// Helper type to access data in the method-specific-id of a [`DidUri`]. | ||
pub struct MethodSpecificId<'a>(&'a DidUri); | ||
|
||
impl MethodSpecificId<'_> { | ||
pub fn as_str(&self) -> &str { | ||
&(self.0.as_str()[self.0.method_specific_id.clone()]) | ||
} | ||
|
||
pub fn as_slice(&self) -> &[u8] { | ||
&(self.0.s.as_slice()[self.0.method_specific_id.clone()]) | ||
} | ||
|
||
pub fn utf8_bytes(&self) -> Utf8Bytes { | ||
self.0.s.clone().split_off(self.0.method_specific_id.start) | ||
} | ||
} | ||
|
||
#[derive(Debug, Eq, PartialEq, Hash)] | ||
pub struct DidUri { | ||
method: DidMethod, | ||
/// 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 DidUri { | ||
/// 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 byte slice that is guaranteed to be utf8. | ||
pub fn 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 | ||
} | ||
|
||
/// Method-specific identity info. | ||
pub fn method_specific_id(&self) -> MethodSpecificId { | ||
MethodSpecificId(self) | ||
} | ||
|
||
pub fn into_inner(self) -> Utf8Bytes { | ||
self.s | ||
} | ||
} | ||
|
||
impl FromStr for DidUri { | ||
type Err = ParseError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
let (method, remaining) = s | ||
.strip_prefix("did:") | ||
.ok_or(ParseError::InvalidScheme)? | ||
.split_once(':') | ||
.ok_or(ParseError::MissingMethod)?; | ||
let method = DidMethod::from_str(method)?; | ||
let start_idx = s.len() - remaining.len(); | ||
|
||
Ok(DidUri { | ||
method, | ||
s: Utf8Bytes::from(s.to_owned()), | ||
method_specific_id: (start_idx..), | ||
}) | ||
} | ||
} | ||
|
||
impl TryFrom<String> for DidUri { | ||
type Error = ParseError; | ||
|
||
fn try_from(s: String) -> Result<Self, Self::Error> { | ||
let (method, remaining) = s | ||
.strip_prefix("did:") | ||
.ok_or(ParseError::InvalidScheme)? | ||
.split_once(':') | ||
.ok_or(ParseError::MissingMethod)?; | ||
let method = DidMethod::from_str(method)?; | ||
let start_idx = s.len() - remaining.len(); | ||
|
||
Ok(DidUri { | ||
method, | ||
s: Utf8Bytes::from(s), | ||
method_specific_id: (start_idx..), | ||
}) | ||
} | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum ParseError { | ||
#[error("expected the did: scheme")] | ||
InvalidScheme, | ||
#[error("expected did:method, but method was not present")] | ||
MissingMethod, | ||
#[error("encountered unknown did:method")] | ||
UnknownMethod, | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use eyre::{Result, WrapErr}; | ||
|
||
#[test] | ||
fn test_parse() -> Result<()> { | ||
let test_cases = [DidUri { | ||
method: DidMethod::Key, | ||
s: String::from("did:key:123456").into(), | ||
method_specific_id: (8..), | ||
}]; | ||
for expected in 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")?; | ||
assert_eq!(from_str, try_from); | ||
assert_eq!(from_str, expected); | ||
} | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.