noosphere_core/data/
strings.rs1use anyhow::Result;
2use noosphere_collections::hamt::Hash as HamtHash;
3use serde::{Deserialize, Serialize};
4use std::{fmt::Display, hash::Hash, ops::Deref, sync::Arc};
5use ucan::crypto::{did::DidParser, KeyMaterial};
6
7use crate::authority::{restore_ed25519_key, SUPPORTED_KEYS};
8
9macro_rules! string_coherent {
12 ($wrapper:ty) => {
13 impl Deref for $wrapper {
14 type Target = String;
15
16 fn deref(&self) -> &Self::Target {
17 &self.0
18 }
19 }
20
21 impl Hash for $wrapper {
22 fn hash<H>(&self, hasher: &mut H)
23 where
24 H: std::hash::Hasher,
25 {
26 Hash::hash(&self.0, hasher)
27 }
28 }
29
30 impl HamtHash for $wrapper {
31 fn hash<H>(&self, hasher: &mut H)
32 where
33 H: std::hash::Hasher,
34 {
35 Hash::hash(&self.0, hasher)
36 }
37 }
38
39 impl From<&str> for $wrapper {
40 fn from(value: &str) -> Self {
41 Self(value.to_owned())
42 }
43 }
44
45 impl From<String> for $wrapper {
46 fn from(value: String) -> Self {
47 Self(value)
48 }
49 }
50
51 impl From<$wrapper> for String {
52 fn from(value: $wrapper) -> Self {
53 value.0
54 }
55 }
56
57 impl<'a> From<&'a $wrapper> for &'a str {
58 fn from(value: &'a $wrapper) -> Self {
59 &value.0
60 }
61 }
62
63 impl PartialEq<String> for $wrapper {
64 fn eq(&self, other: &String) -> bool {
65 &self.0 == other
66 }
67 }
68
69 impl PartialEq<$wrapper> for String {
70 fn eq(&self, other: &$wrapper) -> bool {
71 self == &other.0
72 }
73 }
74
75 impl PartialEq<str> for $wrapper {
76 fn eq(&self, other: &str) -> bool {
77 &self.0 == other
78 }
79 }
80
81 impl PartialEq<$wrapper> for str {
82 fn eq(&self, other: &$wrapper) -> bool {
83 self == &other.0
84 }
85 }
86
87 impl PartialEq<&str> for $wrapper {
88 fn eq(&self, other: &&str) -> bool {
89 &self.0 == *other
90 }
91 }
92
93 impl<'a> PartialEq<$wrapper> for &'a str {
94 fn eq(&self, other: &$wrapper) -> bool {
95 **self == *other.0
96 }
97 }
98
99 impl PartialEq for $wrapper {
100 fn eq(&self, other: &Self) -> bool {
101 self.0 == other.0
102 }
103 }
104
105 impl Eq for $wrapper {}
106
107 impl Display for $wrapper {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 Display::fmt(&self.0, f)
110 }
111 }
112
113 impl AsRef<[u8]> for $wrapper {
114 fn as_ref(&self) -> &[u8] {
115 self.0.as_ref()
116 }
117 }
118 };
119}
120
121#[repr(transparent)]
128#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialOrd, Ord)]
129pub struct Did(pub String);
130
131string_coherent!(Did);
132
133impl Did {
134 pub fn to_credential(&self) -> Result<Arc<Box<dyn KeyMaterial>>> {
138 let mut parser = DidParser::new(SUPPORTED_KEYS);
139 parser.parse(self)
140 }
141}
142
143#[repr(transparent)]
150#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialOrd, Ord)]
151pub struct Jwt(pub String);
152
153string_coherent!(Jwt);
154
155#[repr(transparent)]
160#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialOrd, Ord)]
161pub struct Mnemonic(pub String);
162
163string_coherent!(Mnemonic);
164
165impl Mnemonic {
166 pub fn to_credential(&self) -> Result<Arc<Box<dyn KeyMaterial>>> {
170 Ok(Arc::new(Box::new(restore_ed25519_key(self)?)))
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use libipld_cbor::DagCborCodec;
177 use noosphere_storage::{block_deserialize, block_serialize};
178 use serde::{Deserialize, Serialize};
179
180 use crate::data::Did;
181
182 #[test]
183 fn it_serializes_a_did_transparently_as_a_string() {
184 #[derive(Serialize, Deserialize)]
185 struct FooDid {
186 foo: Did,
187 }
188
189 #[derive(Serialize, Deserialize)]
190 struct FooString {
191 foo: String,
192 }
193
194 let string_value = String::from("foobar");
195 let (did_cid, did_block) = block_serialize::<DagCborCodec, _>(&FooDid {
196 foo: Did(string_value.clone()),
197 })
198 .unwrap();
199
200 let (string_cid, string_block) = block_serialize::<DagCborCodec, _>(&FooString {
201 foo: string_value.clone(),
202 })
203 .unwrap();
204
205 assert_eq!(did_cid, string_cid);
206 assert_eq!(did_block, string_block);
207
208 let did_from_string = block_deserialize::<DagCborCodec, FooDid>(&string_block).unwrap();
209 let string_from_did = block_deserialize::<DagCborCodec, FooString>(&did_block).unwrap();
210
211 assert_eq!(did_from_string.foo, Did(string_value.clone()));
212 assert_eq!(string_from_did.foo, string_value);
213 }
214
215 #[test]
216 fn it_enables_comparison_to_string_types() {
217 let did_str = "did:key:z6MkoE19WHXJzpLqkxbGP7uXdJX38sWZNUWwyjcuCmjhPpUP";
218 let did_string = String::from(did_str);
219 let did = Did::from(did_str);
220
221 assert_eq!(did, did_str);
223 assert_eq!(did_str, did);
224
225 assert_eq!(did, did_string);
227 assert_eq!(did_string, did);
228
229 assert_eq!(&did, did_str);
231 assert_eq!(did_str, &did);
232
233 assert_eq!(&did, &did_string);
235 assert_eq!(&did_string, &did);
236 }
237}