use bc_components::{Digest, DigestProvider};
use dcbor::prelude::*;
use crate::{Envelope, EnvelopeEncodable, Error, Result};
#[derive(Clone, Debug)]
pub struct Assertion {
predicate: Envelope,
object: Envelope,
digest: Digest,
}
impl Assertion {
pub fn new(
predicate: impl EnvelopeEncodable,
object: impl EnvelopeEncodable,
) -> Self {
let predicate = predicate.into_envelope();
let object = object.into_envelope();
let digest =
Digest::from_digests(&[predicate.digest(), object.digest()]);
Self { predicate, object, digest }
}
pub fn predicate(&self) -> Envelope { self.predicate.clone() }
pub fn object(&self) -> Envelope { self.object.clone() }
}
impl PartialEq for Assertion {
fn eq(&self, other: &Self) -> bool { self.digest() == other.digest() }
}
impl Eq for Assertion {}
impl DigestProvider for Assertion {
fn digest(&self) -> Digest { self.digest }
}
impl From<Assertion> for CBOR {
fn from(value: Assertion) -> Self {
let mut map = Map::new();
map.insert(
value.predicate.untagged_cbor(),
value.object.untagged_cbor(),
);
map.into()
}
}
impl TryFrom<CBOR> for Assertion {
type Error = Error;
fn try_from(value: CBOR) -> Result<Self> {
if let CBORCase::Map(map) = value.as_case() {
return map.clone().try_into();
}
Err(Error::InvalidAssertion)
}
}
impl TryFrom<Map> for Assertion {
type Error = Error;
fn try_from(map: Map) -> Result<Self> {
if map.len() != 1 {
return Err(Error::InvalidAssertion);
}
let elem = map.iter().next().unwrap();
let predicate = Envelope::from_untagged_cbor(elem.0.clone())?;
let object = Envelope::from_untagged_cbor(elem.1.clone())?;
Ok(Self::new(predicate, object))
}
}