use super::{ContentAddress, DomainTag, IdentityProfile, IdentityProfileVersion};
use crate::identity::HARNESS_IDENTITY_PROFILE;
impl IdentityProfileVersion {
#[must_use]
pub const fn declared(position: u32) -> Self {
Self(position)
}
#[must_use]
pub const fn position(self) -> u32 {
self.0
}
}
impl DomainTag {
#[must_use]
pub const fn declared(spelling: &'static str, version: IdentityProfileVersion) -> Self {
let mut remaining = spelling.as_bytes();
while let [byte, tail @ ..] = remaining {
assert!(
matches!(*byte, b'a'..=b'z' | b'0'..=b'9' | b'-'),
"a domain tag contains a byte outside its declared character grammar"
);
remaining = tail;
}
Self { spelling, version }
}
#[must_use]
pub const fn spelling(self) -> &'static str {
self.spelling
}
#[must_use]
pub const fn version(self) -> IdentityProfileVersion {
self.version
}
}
impl IdentityProfile {
#[must_use]
pub const fn declared(stem: &'static str) -> Self {
Self { stem }
}
#[must_use]
pub const fn stem(self) -> &'static str {
self.stem
}
#[must_use]
pub fn context_for(self, tag: DomainTag) -> String {
let stem = self.stem;
let family = tag.spelling();
let version = tag.version().position();
format!("{stem}/{family}/v{version}")
}
}
impl ContentAddress {
#[must_use]
pub fn derived(tag: DomainTag, preimage: &[u8]) -> Self {
Self(blake3::derive_key(
&HARNESS_IDENTITY_PROFILE.context_for(tag),
preimage,
))
}
#[must_use]
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}