minerva 0.2.0

Causal ordering for distributed systems
/// A store shape a [`Node`](super::Node) can carry content under: the kind.
///
/// A kind is a *shape*, never a meaning: `Register` is multi-value payload
/// ([`DotFun`](crate::metis::DotFun)), `Map` is caller-keyed children
/// ([`DotMap`](crate::metis::DotMap) of nodes, the recursion), `Sequence` is
/// ordered elements ([`Rhapsody`](crate::metis::Rhapsody)). What a "paragraph"
/// or a "table" *is* stays the caller's vocabulary, carried in its own keys
/// and payloads; minerva reads kinds only to route content and to surface
/// kind conflicts honestly (PRD 0020). The variants order `Register < Map <
/// Sequence`, the enumeration order of every kind read.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Kind {
    /// Multi-value register content: per dot, the value that write carried.
    Register,
    /// Caller-keyed children, each itself a node: the recursive map shape.
    Map,
    /// Ordered elements identified by dots: the sequence shape.
    Sequence,
}

/// A set of [`Kind`]s: the value of the surfaced kind-plurality read
/// ([`Node::kinds_present`](super::Node::kinds_present)).
///
/// At most three members, so the set is a plain `Copy` value; iteration
/// yields kinds in the fixed `Register < Map < Sequence` order. Emptiness
/// means no surviving support of any kind (the lattice bottom, or a node
/// reduced to ordering residue), and a set of two or more is a surfaced kind
/// conflict the caller resolves (the machine never chooses; the kairotic tag
/// is the designed display discriminator, horizons axis 8).
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Kinds {
    /// Whether [`Kind::Register`] is in evidence.
    register: bool,
    /// Whether [`Kind::Map`] is in evidence.
    map: bool,
    /// Whether [`Kind::Sequence`] is in evidence.
    sequence: bool,
}

impl Kinds {
    /// The empty set: no kind in evidence.
    #[must_use]
    pub const fn new() -> Self {
        Self {
            register: false,
            map: false,
            sequence: false,
        }
    }

    /// Marks `kind` as in evidence (idempotent; the reads that build the set
    /// fold every evidence source through here).
    pub(super) const fn insert(&mut self, kind: Kind) {
        match kind {
            Kind::Register => self.register = true,
            Kind::Map => self.map = true,
            Kind::Sequence => self.sequence = true,
        }
    }

    /// Whether `kind` is in evidence.
    #[must_use]
    pub const fn contains(self, kind: Kind) -> bool {
        match kind {
            Kind::Register => self.register,
            Kind::Map => self.map,
            Kind::Sequence => self.sequence,
        }
    }

    /// How many kinds are in evidence (0 through 3).
    #[must_use]
    pub fn len(self) -> usize {
        usize::from(self.register) + usize::from(self.map) + usize::from(self.sequence)
    }

    /// Whether no kind is in evidence: the empty set. On a node this means
    /// no surviving support of any kind (the lattice bottom, or a node
    /// reduced to ordering residue).
    #[must_use]
    pub const fn is_empty(self) -> bool {
        !(self.register || self.map || self.sequence)
    }

    /// The sole kind in evidence, if the set is a singleton; `None` for the
    /// empty set and for every plurality.
    #[must_use]
    pub const fn sole(self) -> Option<Kind> {
        match (self.register, self.map, self.sequence) {
            (true, false, false) => Some(Kind::Register),
            (false, true, false) => Some(Kind::Map),
            (false, false, true) => Some(Kind::Sequence),
            _ => None,
        }
    }

    /// Iterates the kinds in evidence, in the fixed `Register < Map <
    /// Sequence` order.
    pub fn iter(self) -> impl Iterator<Item = Kind> {
        [
            (self.register, Kind::Register),
            (self.map, Kind::Map),
            (self.sequence, Kind::Sequence),
        ]
        .into_iter()
        .filter_map(|(present, kind)| present.then_some(kind))
    }
}

/// The refused outcome of [`Node::sole`](super::Node::sole): more than one
/// kind is in evidence, so no single kind's content can honestly be handed
/// out.
///
/// The typed cross-kind read refusal the parallel-maps recipe could not
/// express (PRD 0019 stage A, recorded hurt: "nothing refuses reading one
/// kind's map for a block whose tag says another"). The witness carries the
/// whole surfaced set so the caller can resolve the plurality itself, off
/// the raw component reads; resolution (which kind to display, whether to
/// re-tag in one covered delta) stays caller policy forever.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct KindPlurality {
    /// The kinds in evidence, at least two.
    pub kinds: Kinds,
}