use crate::HostTypes;
pub trait LayoutInvariant<H: HostTypes> {
fn layout_rule(&self) -> &H::HostString;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NullLayoutInvariant<H: HostTypes> {
_phantom: core::marker::PhantomData<H>,
}
impl<H: HostTypes> Default for NullLayoutInvariant<H> {
fn default() -> Self {
Self {
_phantom: core::marker::PhantomData,
}
}
}
impl<H: HostTypes> NullLayoutInvariant<H> {
pub const ABSENT: NullLayoutInvariant<H> = NullLayoutInvariant {
_phantom: core::marker::PhantomData,
};
}
impl<H: HostTypes> LayoutInvariant<H> for NullLayoutInvariant<H> {
fn layout_rule(&self) -> &H::HostString {
H::EMPTY_HOST_STRING
}
}
#[derive(Debug)]
pub struct LayoutInvariantHandle<H: HostTypes> {
pub fingerprint: crate::enforcement::ContentFingerprint,
_phantom: core::marker::PhantomData<H>,
}
impl<H: HostTypes> Copy for LayoutInvariantHandle<H> {}
impl<H: HostTypes> Clone for LayoutInvariantHandle<H> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<H: HostTypes> PartialEq for LayoutInvariantHandle<H> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.fingerprint == other.fingerprint
}
}
impl<H: HostTypes> Eq for LayoutInvariantHandle<H> {}
impl<H: HostTypes> core::hash::Hash for LayoutInvariantHandle<H> {
#[inline]
fn hash<S: core::hash::Hasher>(&self, state: &mut S) {
self.fingerprint.hash(state);
}
}
impl<H: HostTypes> LayoutInvariantHandle<H> {
#[inline]
#[must_use]
pub const fn new(fingerprint: crate::enforcement::ContentFingerprint) -> Self {
Self {
fingerprint,
_phantom: core::marker::PhantomData,
}
}
}
pub trait LayoutInvariantResolver<H: HostTypes> {
fn resolve(&self, handle: LayoutInvariantHandle<H>) -> Option<LayoutInvariantRecord<H>>;
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct LayoutInvariantRecord<H: HostTypes> {
pub layout_rule: &'static H::HostString,
#[doc(hidden)]
pub _phantom: core::marker::PhantomData<H>,
}
pub struct ResolvedLayoutInvariant<'r, R: LayoutInvariantResolver<H>, H: HostTypes> {
handle: LayoutInvariantHandle<H>,
resolver: &'r R,
record: Option<LayoutInvariantRecord<H>>,
}
impl<'r, R: LayoutInvariantResolver<H>, H: HostTypes> ResolvedLayoutInvariant<'r, R, H> {
#[inline]
pub fn new(handle: LayoutInvariantHandle<H>, resolver: &'r R) -> Self {
let record = resolver.resolve(handle);
Self {
handle,
resolver,
record,
}
}
#[inline]
#[must_use]
pub const fn handle(&self) -> LayoutInvariantHandle<H> {
self.handle
}
#[inline]
#[must_use]
pub const fn resolver(&self) -> &'r R {
self.resolver
}
#[inline]
#[must_use]
pub const fn record(&self) -> Option<&LayoutInvariantRecord<H>> {
self.record.as_ref()
}
}
impl<'r, R: LayoutInvariantResolver<H>, H: HostTypes> LayoutInvariant<H>
for ResolvedLayoutInvariant<'r, R, H>
{
fn layout_rule(&self) -> &H::HostString {
match &self.record {
Some(r) => r.layout_rule,
None => H::EMPTY_HOST_STRING,
}
}
}
pub mod product_layout_width {
pub const LAYOUT_RULE: &str = "SITE_COUNT(A × B) = SITE_COUNT(A) + SITE_COUNT(B)";
}
pub mod cartesian_layout_width {
pub const LAYOUT_RULE: &str = "SITE_COUNT(A ⊠ B) = SITE_COUNT(A) + SITE_COUNT(B)";
}
pub mod coproduct_layout_width {
pub const LAYOUT_RULE: &str = "SITE_COUNT(A + B) = max(SITE_COUNT(A), SITE_COUNT(B)) + 1";
}
pub mod coproduct_tag_encoding {
pub const LAYOUT_RULE: &str =
"Affine { coefficients: [0,…,0, 1 at tag_site], bias: 0 (left) | −1 (right) }";
}