don't
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore(identity): satiate pedantic clippy

Signed-off-by: tjh <x@tjh.dev>

tjh 7b6fd3ee 27c78e98

+52 -150
+15 -3
crates/gordian-identity/src/document.rs
··· 46 46 } 47 47 48 48 impl DidDocument { 49 + /// Construct a new DID document with `handle` and a DID parsed `id`. . 50 + /// 51 + /// # Errors 52 + /// 53 + /// Returns an error if `id` is not a valid DID. 54 + /// 55 + /// # Panics 56 + /// 57 + /// Panics if `handle` is not a valid Athmosphere handle 58 + /// 49 59 pub fn new(id: &str, handle: &str) -> Result<Self, gordian_types::did::Error> { 50 60 let id = id.parse()?; 51 61 Ok(Self { 52 - context: Default::default(), 62 + context: Vec::new(), 53 63 id, 54 64 also_known_as: vec![Url::parse(&format!("at://{handle}")).expect("valid handle")], 55 - verification_method: Default::default(), 56 - service: Default::default(), 65 + verification_method: Vec::new(), 66 + service: Vec::new(), 57 67 }) 58 68 } 59 69 70 + /// Get the primary alias from the document. 60 71 #[must_use] 61 72 pub fn primary_alias(&self) -> Option<&str> { 62 73 self.also_known_as ··· 75 64 .and_then(|at_uri| at_uri.domain()) 76 65 } 77 66 67 + /// Get the Personal Data Server from the document. 78 68 #[must_use] 79 69 pub fn atproto_pds(&self) -> Option<&Service> { 80 70 self.service.iter().find(|service| {
+29 -51
crates/gordian-identity/src/lib.rs
··· 10 10 pub use document::{DidDocument, Service, VerificationMethod}; 11 11 pub use gordian_types::did::Did; 12 12 13 - use crate::resolvers::mock::MockResolver; 14 - 15 13 pub const DEFAULT_PLC_DIRECTORY: &str = "https://plc.directory"; 16 14 17 15 pub type HttpClient = reqwest::Client; ··· 63 65 /// [`ResolveIdentity::resolve`] should be preferred. 64 66 /// 65 67 /// Related: <https://docs.bsky.app/docs/api/com-atproto-identity-resolve-handle> 68 + /// 69 + /// # Errors 70 + /// 71 + /// Returns an error `handle` cannot be resolved to a DID. 72 + /// 66 73 fn resolve_handle<'s: 'h, 'h>( 67 74 &'s self, 68 75 handle: &'h str, ··· 80 77 /// [`ResolveIdentity::resolve`] should be preferred. 81 78 /// 82 79 /// Ref: <https://docs.bsky.app/docs/api/com-atproto-identity-resolve-did> 80 + /// 81 + /// # Errors 82 + /// 83 + /// Returns an error if `did` cannot be resolved to a DID document. 84 + /// 83 85 fn resolve_did<'s: 'd, 'd>( 84 86 &'s self, 85 87 did: &'d Did, ··· 128 120 } 129 121 130 122 impl Resolver { 123 + /// Create a new type-erased resolver from another resolver. 131 124 pub fn new<R>(resolver: R) -> Self 132 125 where 133 126 R: ResolveIdentity + Send + 'static, ··· 137 128 Self { inner } 138 129 } 139 130 140 - #[must_use] 141 131 pub fn builder() -> ResolverBuilder { 142 132 ResolverBuilder::new() 143 133 } 144 134 145 135 /// Resolve a handle or a DID to a DID document. 136 + /// 137 + /// # Errors 138 + /// 139 + /// Returns a error if `ident` cannot be resolved. This included bi-directional resolution 140 + /// errors. 141 + /// 146 142 pub async fn resolve(&self, ident: &str) -> Result<(OwnedDid, DidDocument), ResolveError> { 147 143 let ident = ident.trim_start_matches('@'); 148 144 self.inner.resolve(ident).await 149 145 } 150 146 151 147 /// Resolve a handle to a DID. 148 + /// 149 + /// # Errors 150 + /// 151 + /// Returns a error if `handle` cannot be resolved to a DID. 152 + /// 152 153 #[inline] 153 154 pub async fn resolve_handle(&self, handle: &str) -> Result<OwnedDid, ResolveError> { 154 155 let handle = handle.trim_start_matches('@'); ··· 166 147 } 167 148 168 149 /// Resolve a DID to a DID document. 150 + /// 151 + /// # Errors 152 + /// 153 + /// Returns a error if `did` cannot be resolved to a DID document. 154 + /// 169 155 #[inline] 170 156 pub async fn resolve_did(&self, did: &Did) -> Result<DidDocument, ResolveError> { 171 157 self.inner.resolve_did(did).await ··· 179 155 #[inline] 180 156 pub async fn invalidate_did(&self, did: &Did) { 181 157 self.inner.invalidate_did(did).await; 182 - } 183 - } 184 - 185 - impl Resolver { 186 - /// Create a mock resolver, which only resolves the specified identities from 187 - /// memory. 188 - /// 189 - /// The underlying [`MockResolver`] is returned along with the type-erased [`Resolver`] to 190 - /// enable access to [`MockResolver::insert`]. 191 - /// 192 - pub fn mocked(documents: impl IntoIterator<Item = DidDocument>) -> (Self, MockResolver) { 193 - let resolver = MockResolver::new(documents); 194 - let mocked = resolver.clone(); 195 - let inner = Arc::new(resolver); 196 - (Self { inner }, mocked) 197 158 } 198 159 } 199 160 ··· 209 200 } 210 201 } 211 202 203 + #[must_use] 212 204 pub struct ResolverBuilder { 213 205 backend: ResolverBackend, 214 206 plc_directory: std::borrow::Cow<'static, str>, ··· 218 208 } 219 209 220 210 impl ResolverBuilder { 221 - #[must_use] 222 211 pub fn new() -> Self { 223 212 Self { 224 - backend: Default::default(), 213 + backend: ResolverBackend::default(), 225 214 plc_directory: DEFAULT_PLC_DIRECTORY.into(), 226 215 cache_capacity: 1000, 227 216 cache_ttl: std::time::Duration::from_secs(1000), ··· 230 221 /// Use [`DirectResolver`] as the backend resolver. 231 222 /// 232 223 /// This resolver does not cache DIDs or DID documents. 233 - #[must_use] 234 224 pub const fn direct(mut self) -> Self { 235 225 self.backend = ResolverBackend::Direct; 236 226 self 237 227 } 238 228 239 229 /// Use [`MemcacheResolver`] as the backend resolver. 240 - #[must_use] 241 230 pub const fn memcache(mut self) -> Self { 242 231 self.backend = ResolverBackend::Memcache; 243 232 self ··· 244 237 /// Set the cache capacity for both DIDs and DID documents. 245 238 /// 246 239 /// Ignored if backend resolver does not support caching. 247 - #[must_use] 248 240 pub const fn cache_capacity(mut self, cap: u64) -> Self { 249 241 self.cache_capacity = cap; 250 242 self ··· 252 246 /// Set the cache Time-To-Live for both DIDs and DID documents. 253 247 /// 254 248 /// Ignored if backend resolver does not support caching. 255 - #[must_use] 256 249 pub const fn cache_ttl(mut self, ttl: std::time::Duration) -> Self { 257 250 self.cache_ttl = ttl; 258 251 self ··· 305 300 Direct, 306 301 #[default] 307 302 Memcache, 308 - } 309 - 310 - #[cfg(test)] 311 - mod tests { 312 - use super::*; 313 - 314 - #[tokio::test] 315 - async fn empty_mock_resolver() { 316 - let (resolver, _) = Resolver::mocked([]); 317 - assert!(matches!( 318 - resolver.resolve("tjh.dev").await, 319 - Err(ResolveError::UnresolvedHandle) 320 - )); 321 - } 322 - 323 - #[tokio::test] 324 - async fn mock_resolver() { 325 - let (resolver, _) = 326 - Resolver::mocked([ 327 - DidDocument::new("did:plc:65gha4t3avpfpzmvpbwovss7", "tjh.dev") 328 - .expect("valid did document"), 329 - ]); 330 - 331 - let (did, doc) = resolver.resolve("tjh.dev").await.expect("resolved id"); 332 - assert_eq!(did.as_ref(), "did:plc:65gha4t3avpfpzmvpbwovss7"); 333 - assert_eq!(doc.primary_alias(), Some("tjh.dev")); 334 - } 335 303 }
-1
crates/gordian-identity/src/resolvers.rs
··· 1 1 pub mod direct; 2 2 pub mod memcache; 3 - pub mod mock;
+8 -2
crates/gordian-identity/src/resolvers/direct.rs
··· 126 126 self 127 127 } 128 128 129 + /// Build the resolver. 130 + /// 131 + /// # Panics 132 + /// 133 + /// Panics if the dns resolver cannot be initialised. 134 + /// 129 135 #[must_use] 130 136 pub fn build_with(self, http: HttpClient) -> DirectResolver<'plc, TokioConnectionProvider> { 131 137 DirectResolver { ··· 144 138 } 145 139 } 146 140 147 - pub async fn resolve_handle_dns<R>( 141 + async fn resolve_handle_dns<R>( 148 142 client: &DnsClient<R>, 149 143 handle: &str, 150 144 ) -> Result<Option<OwnedDid>, DnsResolveError> ··· 184 178 Ok(resolved_did) 185 179 } 186 180 187 - pub async fn resolve_handle_http( 181 + async fn resolve_handle_http( 188 182 client: &HttpClient, 189 183 handle: &str, 190 184 ) -> Result<Option<OwnedDid>, reqwest::Error> {
-93
crates/gordian-identity/src/resolvers/mock.rs
··· 1 - use std::{ 2 - collections::HashMap, 3 - sync::{Arc, Mutex}, 4 - }; 5 - 6 - use futures_util::{FutureExt, future::BoxFuture}; 7 - use gordian_types::OwnedDid; 8 - 9 - use crate::{DidDocument, ResolveError, ResolveIdentity}; 10 - 11 - #[derive(Debug, Default)] 12 - struct Inner { 13 - handle_did: HashMap<String, OwnedDid>, 14 - did_document: HashMap<OwnedDid, DidDocument>, 15 - } 16 - 17 - #[derive(Clone, Debug, Default)] 18 - pub struct MockResolver { 19 - inner: Arc<Mutex<Inner>>, 20 - } 21 - 22 - impl MockResolver { 23 - pub fn new(documents: impl IntoIterator<Item = DidDocument>) -> Self { 24 - let mut handle_did = HashMap::default(); 25 - let mut did_document = HashMap::default(); 26 - for (handle, did_val, did_key, document) in documents.into_iter().map(split_document) { 27 - handle_did.insert(handle, did_val); 28 - did_document.insert(did_key, document); 29 - } 30 - 31 - let inner = Arc::new(Mutex::new(Inner { 32 - handle_did, 33 - did_document, 34 - })); 35 - 36 - Self { inner } 37 - } 38 - 39 - /// Add an identity to the mock resolver. 40 - pub fn insert(&self, document: DidDocument) { 41 - let (handle, did_val, did_key, document) = split_document(document); 42 - let mut map = self.inner.lock().expect("unpoisoned mutex"); 43 - map.handle_did.insert(handle, did_val); 44 - map.did_document.insert(did_key, document); 45 - } 46 - } 47 - 48 - fn split_document(document: DidDocument) -> (String, OwnedDid, OwnedDid, DidDocument) { 49 - let handle = document 50 - .primary_alias() 51 - .expect("aliased identity") 52 - .to_owned(); 53 - 54 - let did = &document.id; 55 - 56 - (handle, did.to_owned(), did.to_owned(), document) 57 - } 58 - 59 - impl FromIterator<DidDocument> for MockResolver { 60 - fn from_iter<T: IntoIterator<Item = DidDocument>>(iter: T) -> Self { 61 - Self::new(iter) 62 - } 63 - } 64 - 65 - impl ResolveIdentity for MockResolver { 66 - fn resolve_handle<'s: 'h, 'h>( 67 - &'s self, 68 - handle: &'h str, 69 - ) -> BoxFuture<'h, Result<OwnedDid, ResolveError>> { 70 - async move { 71 - let map = self.inner.lock().expect("unpoisoned mutex"); 72 - map.handle_did 73 - .get(handle) 74 - .ok_or(ResolveError::UnresolvedHandle) 75 - .cloned() 76 - } 77 - .boxed() 78 - } 79 - 80 - fn resolve_did<'s: 'd, 'd>( 81 - &'s self, 82 - did: &'d gordian_types::Did, 83 - ) -> BoxFuture<'d, Result<DidDocument, ResolveError>> { 84 - async move { 85 - let map = self.inner.lock().expect("unpoisoned mutex"); 86 - map.did_document 87 - .get(did) 88 - .ok_or(ResolveError::UnresolvedHandle) 89 - .cloned() 90 - } 91 - .boxed() 92 - } 93 - }