use crate::{
derive::raw,
domain::{DeriveDomain, Domain},
encode::{from_base58_to_32, to_base58, to_hex},
error::Error,
};
pub const DID_PREFIX: &str = "did:agid:";
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Did {
raw: [u8; 32],
domain: Domain,
}
impl Did {
#[inline]
#[must_use]
pub fn derive(domain: DeriveDomain, input: &[u8]) -> Self {
Self {
raw: raw(domain.as_byte(), input),
domain: domain.into(),
}
}
#[inline]
#[must_use]
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.raw
}
#[inline]
#[must_use]
pub const fn domain(&self) -> Domain {
self.domain
}
#[must_use]
pub fn to_hex_array(&self) -> [u8; 64] {
to_hex(&self.raw)
}
#[cfg(feature = "std")]
#[must_use]
pub fn to_did_string(&self) -> std::string::String {
let (buf, len) = to_base58(&self.raw);
let mut s = std::string::String::with_capacity(DID_PREFIX.len() + len);
s.push_str(DID_PREFIX);
s.push_str(core::str::from_utf8(&buf[..len]).unwrap_or(""));
s
}
#[inline]
#[must_use]
pub const fn from_bytes(raw: [u8; 32]) -> Self {
Self {
raw,
domain: Domain::Opaque,
}
}
pub fn parse(s: &str) -> Result<Self, Error> {
let payload = s.strip_prefix(DID_PREFIX).ok_or(Error::MissingPrefix)?;
if payload.is_empty() || payload.len() > 44 {
return Err(Error::WrongLength);
}
if !payload.is_ascii() {
return Err(Error::InvalidBase58);
}
let raw = from_base58_to_32(payload.as_bytes()).ok_or(Error::InvalidBase58)?;
Ok(Self::from_bytes(raw))
}
#[inline]
#[must_use]
pub fn eq_bytes(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
#[cfg(feature = "std")]
impl core::str::FromStr for Did {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s)
}
}
impl core::fmt::Display for Did {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let (buf, len) = to_base58(&self.raw);
write!(
f,
"did:agid:{}",
core::str::from_utf8(&buf[..len]).unwrap_or("")
)
}
}
impl core::fmt::Debug for Did {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let hex = to_hex(&self.raw);
write!(
f,
"Did({}/{})",
self.domain,
core::str::from_utf8(&hex).unwrap_or("?")
)
}
}