use crate::HostTypes;
pub trait Element<H: HostTypes> {
fn length(&self) -> u64;
fn addresses(&self) -> &H::HostString;
fn digest(&self) -> &H::HostString;
fn digest_algorithm(&self) -> &H::HostString;
fn canonical_bytes(&self) -> &H::WitnessBytes;
fn witt_length(&self) -> u64;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NullElement<H: HostTypes> {
_phantom: core::marker::PhantomData<H>,
}
impl<H: HostTypes> Default for NullElement<H> {
fn default() -> Self {
Self {
_phantom: core::marker::PhantomData,
}
}
}
impl<H: HostTypes> NullElement<H> {
pub const ABSENT: NullElement<H> = NullElement {
_phantom: core::marker::PhantomData,
};
}
impl<H: HostTypes> Element<H> for NullElement<H> {
fn length(&self) -> u64 {
0
}
fn addresses(&self) -> &H::HostString {
H::EMPTY_HOST_STRING
}
fn digest(&self) -> &H::HostString {
H::EMPTY_HOST_STRING
}
fn digest_algorithm(&self) -> &H::HostString {
H::EMPTY_HOST_STRING
}
fn canonical_bytes(&self) -> &H::WitnessBytes {
H::EMPTY_WITNESS_BYTES
}
fn witt_length(&self) -> u64 {
0
}
}
#[derive(Debug)]
pub struct ElementHandle<H: HostTypes> {
pub fingerprint: crate::enforcement::ContentFingerprint,
_phantom: core::marker::PhantomData<H>,
}
impl<H: HostTypes> Copy for ElementHandle<H> {}
impl<H: HostTypes> Clone for ElementHandle<H> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<H: HostTypes> PartialEq for ElementHandle<H> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.fingerprint == other.fingerprint
}
}
impl<H: HostTypes> Eq for ElementHandle<H> {}
impl<H: HostTypes> core::hash::Hash for ElementHandle<H> {
#[inline]
fn hash<S: core::hash::Hasher>(&self, state: &mut S) {
self.fingerprint.hash(state);
}
}
impl<H: HostTypes> ElementHandle<H> {
#[inline]
#[must_use]
pub const fn new(fingerprint: crate::enforcement::ContentFingerprint) -> Self {
Self {
fingerprint,
_phantom: core::marker::PhantomData,
}
}
}
pub trait ElementResolver<H: HostTypes> {
fn resolve(&self, handle: ElementHandle<H>) -> Option<ElementRecord<H>>;
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ElementRecord<H: HostTypes> {
pub length: u64,
pub addresses: &'static H::HostString,
pub digest: &'static H::HostString,
pub digest_algorithm: &'static H::HostString,
pub canonical_bytes: &'static H::WitnessBytes,
pub witt_length: u64,
#[doc(hidden)]
pub _phantom: core::marker::PhantomData<H>,
}
pub struct ResolvedElement<'r, R: ElementResolver<H>, H: HostTypes> {
handle: ElementHandle<H>,
resolver: &'r R,
record: Option<ElementRecord<H>>,
}
impl<'r, R: ElementResolver<H>, H: HostTypes> ResolvedElement<'r, R, H> {
#[inline]
pub fn new(handle: ElementHandle<H>, resolver: &'r R) -> Self {
let record = resolver.resolve(handle);
Self {
handle,
resolver,
record,
}
}
#[inline]
#[must_use]
pub const fn handle(&self) -> ElementHandle<H> {
self.handle
}
#[inline]
#[must_use]
pub const fn resolver(&self) -> &'r R {
self.resolver
}
#[inline]
#[must_use]
pub const fn record(&self) -> Option<&ElementRecord<H>> {
self.record.as_ref()
}
}
impl<'r, R: ElementResolver<H>, H: HostTypes> Element<H> for ResolvedElement<'r, R, H> {
fn length(&self) -> u64 {
match &self.record {
Some(r) => r.length,
None => 0,
}
}
fn addresses(&self) -> &H::HostString {
H::EMPTY_HOST_STRING
}
fn digest(&self) -> &H::HostString {
match &self.record {
Some(r) => r.digest,
None => H::EMPTY_HOST_STRING,
}
}
fn digest_algorithm(&self) -> &H::HostString {
match &self.record {
Some(r) => r.digest_algorithm,
None => H::EMPTY_HOST_STRING,
}
}
fn canonical_bytes(&self) -> &H::WitnessBytes {
match &self.record {
Some(r) => r.canonical_bytes,
None => H::EMPTY_WITNESS_BYTES,
}
}
fn witt_length(&self) -> u64 {
match &self.record {
Some(r) => r.witt_length,
None => 0,
}
}
}