use async_trait::async_trait;
use std::collections::HashMap;
use crate::{DID, DIDDocument, DIDError};
#[async_trait]
pub trait DIDResolver {
async fn resolve(&self, did: &DID) -> Result<DIDDocument, DIDError>;
async fn resolve_with_options(
&self,
did: &DID,
options: ResolveOptions,
) -> Result<ResolveResult, DIDError>;
}
#[derive(Debug, Default)]
pub struct ResolveOptions {
pub accept: Option<String>,
pub version_id: Option<String>,
pub version_time: Option<String>,
pub no_cache: bool,
}
#[derive(Debug)]
pub struct ResolveResult {
pub document: DIDDocument,
pub metadata: ResolutionMetadata,
pub document_metadata: DocumentMetadata,
}
#[derive(Debug, Default)]
pub struct ResolutionMetadata {
pub content_type: Option<String>,
pub error: Option<String>,
pub properties: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Default)]
pub struct DocumentMetadata {
pub created: Option<String>,
pub updated: Option<String>,
pub deactivated: Option<bool>,
pub version_id: Option<String>,
pub next_version_id: Option<String>,
pub canonical_id: Option<String>,
pub equivalent_id: Option<Vec<String>>,
}
pub struct UniversalResolver {
resolvers: HashMap<String, Box<dyn DIDResolver + Send + Sync>>,
}
impl Default for UniversalResolver {
fn default() -> Self {
Self::new()
}
}
impl UniversalResolver {
pub fn new() -> Self {
Self {
resolvers: HashMap::new(),
}
}
pub fn register_resolver(
&mut self,
method: String,
resolver: Box<dyn DIDResolver + Send + Sync>,
) {
self.resolvers.insert(method, resolver);
}
}
#[async_trait]
impl DIDResolver for UniversalResolver {
async fn resolve(&self, did: &DID) -> Result<DIDDocument, DIDError> {
let resolver = self.resolvers
.get(&did.method)
.ok_or_else(|| DIDError::ResolutionFailed(
format!("No resolver for method: {}", did.method)
))?;
resolver.resolve(did).await
}
async fn resolve_with_options(
&self,
did: &DID,
options: ResolveOptions,
) -> Result<ResolveResult, DIDError> {
let resolver = self.resolvers
.get(&did.method)
.ok_or_else(|| DIDError::ResolutionFailed(
format!("No resolver for method: {}", did.method)
))?;
resolver.resolve_with_options(did, options).await
}
}