1use std::{fmt::Display, str::FromStr};
2
3use fluent_uri::Uri;
4
5use crate::dids::{Did, DidFromUriErr};
6
7#[derive(Debug, Eq, PartialEq, Clone)]
10pub enum VerificationMethod {
11 DidKey(Did),
13 DidUrl(Did),
21}
22
23impl VerificationMethod {
24 pub fn as_did(&self) -> &Did {
25 match self {
26 VerificationMethod::DidKey(did) => did,
27 VerificationMethod::DidUrl(did) => did,
28 }
29 }
30}
31
32#[derive(Debug, thiserror::Error)]
33pub enum ParseVerificationMethodErr {
34 #[error("not a uri")]
35 NotAUri(#[from] fluent_uri::error::ParseError<String>),
36 #[error("did not start with did:")]
37 NotADid(#[from] DidFromUriErr),
38}
39
40impl FromStr for VerificationMethod {
41 type Err = ParseVerificationMethodErr;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 let uri: Uri<String> = Uri::try_from(s.to_owned())?;
45 let did = Did::try_from(uri)?;
46 Ok(Self::from(did))
47 }
48}
49
50impl TryFrom<String> for VerificationMethod {
51 type Error = ParseVerificationMethodErr;
52
53 fn try_from(value: String) -> Result<Self, Self::Error> {
54 let uri: Uri<String> = Uri::try_from(value)?;
55 let did = Did::try_from(uri)?;
56
57 Ok(Self::from(did))
58 }
59}
60
61impl From<Did> for VerificationMethod {
62 fn from(value: Did) -> Self {
63 let (prefix, _suffix) = value
64 .as_uri()
65 .path()
66 .split_once(':')
67 .expect("already checked for did: prefix");
68
69 if prefix == "key" {
70 Self::DidKey(value)
71 } else {
72 Self::DidUrl(value)
73 }
74 }
75}
76
77impl<T: AsRef<str>> PartialEq<T> for VerificationMethod {
78 fn eq(&self, other: &T) -> bool {
79 self.as_did() == other
80 }
81}
82
83impl Display for VerificationMethod {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 write!(f, "{}", self.as_did())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use std::str::FromStr as _;
92
93 use crate::dids::test::{DID_KEY_EXAMPLES, DID_WEB_EXAMPLES};
94 use crate::doc::{vmethod::VerificationMethod, Did};
95
96 #[test]
97 fn test_correct_variant() {
98 for e in DID_WEB_EXAMPLES {
99 let did = Did::from_str(e).unwrap();
100 let parsed = VerificationMethod::from_str(e).unwrap();
101 let try_from = VerificationMethod::from(did.clone());
102 assert_eq!(
103 parsed, try_from,
104 "parsing and try_from were not the same for example {e}"
105 );
106 assert_eq!(parsed, VerificationMethod::DidUrl(did));
107 }
108
109 for e in DID_KEY_EXAMPLES {
110 let did = Did::from_str(e).unwrap();
111 let parsed = VerificationMethod::from_str(e).unwrap();
112 let try_from = VerificationMethod::from(did.clone());
113 assert_eq!(
114 parsed, try_from,
115 "parsing and try_from were not the same for example {e}"
116 );
117 assert_eq!(parsed, VerificationMethod::DidKey(did));
118 }
119 }
120
121 #[test]
122 fn test_as_did() {
123 for e in [DID_KEY_EXAMPLES, DID_WEB_EXAMPLES].concat() {
124 let vm = Did::from_str(e).unwrap();
125 assert_eq!(vm.as_uri(), e, "failed example {e}");
126 }
127 }
128}