use bc_components::ARID;
use bc_envelope::prelude::*;
use super::error::Error;
pub fn create_reference_envelope(
reference_arid: &ARID,
actual_size: usize,
) -> Envelope {
Envelope::unit()
.add_assertion(known_values::DEREFERENCE_VIA, "ipfs")
.add_assertion(known_values::ID, *reference_arid)
.add_assertion("size", actual_size as i64)
}
pub fn is_reference_envelope(envelope: &Envelope) -> bool {
if !envelope.is_subject_unit() {
return false;
}
let has_dereference_via = envelope.assertions().iter().any(|assertion| {
if let Ok(predicate) = assertion.try_predicate()
&& let Some(kv) = predicate.as_known_value()
&& kv.value() == known_values::DEREFERENCE_VIA_RAW
&& let Ok(object) = assertion.try_object()
&& let Ok(cbor) = object.subject().try_leaf()
&& let Ok(text) = cbor.try_into_text()
{
return text == "ipfs";
}
false
});
if !has_dereference_via {
return false;
}
envelope.assertions().iter().any(|assertion| {
if let Ok(predicate) = assertion.try_predicate() {
if let Some(kv) = predicate.as_known_value() {
kv.value() == known_values::ID_RAW
} else {
false
}
} else {
false
}
})
}
pub fn extract_reference_arid(envelope: &Envelope) -> Result<ARID, Error> {
if !is_reference_envelope(envelope) {
return Err(Error::NotReferenceEnvelope);
}
for assertion in envelope.assertions() {
if let Ok(predicate) = assertion.try_predicate()
&& let Some(kv) = predicate.as_known_value()
&& kv.value() == known_values::ID_RAW
{
if let Ok(object) = assertion.try_object()
&& let Ok(cbor) = object.subject().try_leaf()
{
if let Ok(arid) = ARID::try_from(cbor.clone()) {
return Ok(arid);
} else {
return Err(Error::InvalidReferenceArid);
}
}
}
}
Err(Error::NoIdAssertion)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_reference_envelope() {
let reference_arid = ARID::new();
let size = 5000;
let envelope = create_reference_envelope(&reference_arid, size);
assert!(envelope.is_subject_unit());
assert_eq!(envelope.assertions().len(), 3);
}
#[test]
fn test_is_reference_envelope() {
let reference_arid = ARID::new();
let size = 5000;
let reference = create_reference_envelope(&reference_arid, size);
assert!(is_reference_envelope(&reference));
let regular = Envelope::new("test data");
assert!(!is_reference_envelope(®ular));
let wrong_subject = Envelope::new("notunit")
.add_assertion(known_values::DEREFERENCE_VIA, "ipfs")
.add_assertion(known_values::ID, reference_arid);
assert!(!is_reference_envelope(&wrong_subject));
}
#[test]
fn test_extract_reference_arid() {
let reference_arid = ARID::new();
let size = 5000;
let reference = create_reference_envelope(&reference_arid, size);
let extracted = extract_reference_arid(&reference).unwrap();
assert_eq!(extracted, reference_arid);
}
#[test]
fn test_extract_reference_arid_from_non_reference() {
let regular = Envelope::new("test data");
let result = extract_reference_arid(®ular);
assert!(result.is_err());
}
}