use dig_urn_protocol::{Bytes32 as UrnBytes32, DigUrn, CANONICAL_CHAIN};
use crate::error::{DigStoreError, DigStoreResult};
use crate::types::Bytes32;
pub const URN_PREFIX: &str = "urn:dig:chia:";
fn to_urn_bytes(value: Bytes32) -> UrnBytes32 {
let mut raw = [0u8; 32];
raw.copy_from_slice(value.as_ref());
UrnBytes32(raw)
}
pub fn store_urn(store_id: Bytes32) -> String {
DigUrn {
chain: CANONICAL_CHAIN.to_string(),
store_id: to_urn_bytes(store_id),
root_hash: None,
resource_key: None,
}
.canonical()
}
pub fn capsule_urn(store_id: Bytes32, root_hash: Bytes32) -> String {
DigUrn {
chain: CANONICAL_CHAIN.to_string(),
store_id: to_urn_bytes(store_id),
root_hash: Some(to_urn_bytes(root_hash)),
resource_key: None,
}
.canonical()
}
pub fn retrieval_key(urn: &str) -> DigStoreResult<Bytes32> {
let parsed =
DigUrn::parse(urn).map_err(|error| DigStoreError::InvalidUrn(format!("{urn}: {error}")))?;
Ok(Bytes32::new(parsed.retrieval_key().0))
}
#[cfg(test)]
mod tests {
use super::*;
fn id(byte: u8) -> Bytes32 {
Bytes32::new([byte; 32])
}
#[test]
fn prefix_matches_protocol() {
assert_eq!(
URN_PREFIX,
format!("{}{CANONICAL_CHAIN}:", dig_urn_protocol::URN_PREFIX)
);
}
#[test]
fn store_urn_is_rootless() {
let urn = store_urn(id(0xab));
assert_eq!(urn, format!("urn:dig:chia:{}", "ab".repeat(32)));
assert!(!urn.trim_start_matches(URN_PREFIX).contains(':'));
}
#[test]
fn capsule_urn_pins_the_root() {
let urn = capsule_urn(id(0x11), id(0x22));
assert_eq!(
urn,
format!("urn:dig:chia:{}:{}", "11".repeat(32), "22".repeat(32))
);
}
#[test]
fn retrieval_key_matches_dig_urn_protocol() {
let urn = store_urn(id(0x01));
let expected = DigUrn::parse(&urn).unwrap().retrieval_key();
assert_eq!(retrieval_key(&urn).unwrap(), Bytes32::new(expected.0));
}
#[test]
fn store_and_capsule_urns_have_distinct_retrieval_keys() {
let store = store_urn(id(0x05));
let capsule = capsule_urn(id(0x05), id(0x06));
assert_ne!(
retrieval_key(&store).unwrap(),
retrieval_key(&capsule).unwrap()
);
}
#[test]
fn retrieval_key_rejects_a_non_urn() {
assert!(matches!(
retrieval_key("not-a-urn"),
Err(DigStoreError::InvalidUrn(_))
));
}
}