use std::{fmt::Display, str::FromStr};
use fluent_uri::Uri;
use crate::dids::{Did, DidFromUriErr};
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum VerificationMethod {
DidKey(Did),
DidUrl(Did),
}
impl VerificationMethod {
pub fn as_did(&self) -> &Did {
match self {
VerificationMethod::DidKey(did) => did,
VerificationMethod::DidUrl(did) => did,
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum ParseVerificationMethodErr {
#[error("not a uri")]
NotAUri(#[from] fluent_uri::error::ParseError<String>),
#[error("did not start with did:")]
NotADid(#[from] DidFromUriErr),
}
impl FromStr for VerificationMethod {
type Err = ParseVerificationMethodErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let uri: Uri<String> = Uri::try_from(s.to_owned())?;
let did = Did::try_from(uri)?;
Ok(Self::from(did))
}
}
impl TryFrom<String> for VerificationMethod {
type Error = ParseVerificationMethodErr;
fn try_from(value: String) -> Result<Self, Self::Error> {
let uri: Uri<String> = Uri::try_from(value)?;
let did = Did::try_from(uri)?;
Ok(Self::from(did))
}
}
impl From<Did> for VerificationMethod {
fn from(value: Did) -> Self {
let (prefix, _suffix) = value
.as_uri()
.path()
.split_once(':')
.expect("already checked for did: prefix");
if prefix == "key" {
Self::DidKey(value)
} else {
Self::DidUrl(value)
}
}
}
impl<T: AsRef<str>> PartialEq<T> for VerificationMethod {
fn eq(&self, other: &T) -> bool {
self.as_did() == other
}
}
impl Display for VerificationMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_did())
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr as _;
use crate::dids::test::{DID_KEY_EXAMPLES, DID_WEB_EXAMPLES};
use crate::doc::{vmethod::VerificationMethod, Did};
#[test]
fn test_correct_variant() {
for e in DID_WEB_EXAMPLES {
let did = Did::from_str(e).unwrap();
let parsed = VerificationMethod::from_str(e).unwrap();
let try_from = VerificationMethod::from(did.clone());
assert_eq!(
parsed, try_from,
"parsing and try_from were not the same for example {e}"
);
assert_eq!(parsed, VerificationMethod::DidUrl(did));
}
for e in DID_KEY_EXAMPLES {
let did = Did::from_str(e).unwrap();
let parsed = VerificationMethod::from_str(e).unwrap();
let try_from = VerificationMethod::from(did.clone());
assert_eq!(
parsed, try_from,
"parsing and try_from were not the same for example {e}"
);
assert_eq!(parsed, VerificationMethod::DidKey(did));
}
}
#[test]
fn test_as_did() {
for e in [DID_KEY_EXAMPLES, DID_WEB_EXAMPLES].concat() {
let vm = Did::from_str(e).unwrap();
assert_eq!(vm.as_uri(), e, "failed example {e}");
}
}
}