use std::fmt;
use serde::{Deserialize, Serialize};
use super::crypto::hex_encode;
use super::error::DidError;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(try_from = "String", into = "String")]
pub struct Did(String);
impl Did {
pub fn parse(value: impl Into<String>) -> Result<Self, DidError> {
let value = value.into();
let parts: Vec<_> = value.split(':').collect();
if parts.len() < 3 || parts.first() != Some(&"did") || parts[1].is_empty() {
return Err(DidError::InvalidDid(value));
}
Ok(Self(value))
}
pub fn key(public_key: impl AsRef<[u8]>) -> Self {
Self(format!("did:key:z{}", hex_encode(public_key.as_ref())))
}
pub fn web(host: impl AsRef<str>) -> Result<Self, DidError> {
let host = host.as_ref().trim();
if host.is_empty() || host.contains('/') {
return Err(DidError::InvalidDid(format!("did:web:{host}")));
}
Ok(Self(format!("did:web:{host}")))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for Did {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl TryFrom<String> for Did {
type Error = DidError;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::parse(value)
}
}
impl From<Did> for String {
fn from(value: Did) -> Self {
value.0
}
}