minerva 0.2.0

Causal ordering for distributed systems
use crate::metis::{DotFun, DotMap, DotStore, Rhapsody};

use super::{Kind, KindPlurality, Kinds, Node};

/// One kind's content, as [`Node::sole`] hands it out: the typed projection
/// that cannot read one kind's content for a node whose evidence says
/// another.
///
/// The reference may be a bottom component: a node whose tag is present with
/// bottom content is *empty of that kind* (an empty paragraph, a
/// just-retyped block), and the empty component is the honest content.
#[derive(Clone, Copy, Debug)]
pub enum NodeContent<'a, K, V> {
    /// Register content: the surviving payload writes.
    Register(&'a DotFun<V>),
    /// Map content: the live caller-keyed children.
    Map(&'a DotMap<K, Node<K, V>>),
    /// Sequence content: the ordered elements.
    Sequence(&'a Rhapsody),
}

impl<K: Ord + Clone, V: Clone> Node<K, V> {
    /// The kinds in evidence on this node: every kind a surviving tag write
    /// claims, plus every kind whose content component carries surviving
    /// support.
    ///
    /// The surfaced kind-plurality read (ruling R-17's second leg). One kind
    /// is the honest steady state; two or more is a surfaced conflict
    /// (concurrent kind writes, or content that survived concurrently with a
    /// re-kinding) the caller resolves, never the machine. A tag-only node
    /// evidences its tagged kind (emptiness representable), and content that
    /// outlived its tag (a concurrent write the survivor law rightly kept)
    /// still evidences its shape, so nothing *readable* is ever hidden from
    /// the summary.
    ///
    /// Evidence rides *surviving support* (the survivor law's coordinate),
    /// never recording state: a sequence whose every element was superseded
    /// keeps its grow-only ordering skeleton (the
    /// [`Rhapsody`](crate::metis::Rhapsody) posture) but evidences no kind,
    /// because order tombstones are recording, not content. The set is
    /// therefore empty exactly when the node carries no surviving dot: at
    /// the lattice bottom, and on a node reduced to ordering residue by an
    /// honest re-kinding or full deletion (the residue awaits the retention
    /// face, [`condense`](crate::metis::Rhapsody::condense)).
    #[must_use]
    pub fn kinds_present(&self) -> Kinds {
        let mut kinds = Kinds::new();
        for kind in self.tag().values() {
            kinds.insert(*kind);
        }
        if !self.register().is_empty() {
            kinds.insert(Kind::Register);
        }
        // Support, not key presence: a child key can outlive its support on
        // sequence residue alone (a non-bottom child with no surviving dot),
        // and residue is not evidence at the parent either.
        if self.children().dots().next().is_some() {
            kinds.insert(Kind::Map);
        }
        if self.sequence().dots().next().is_some() {
            kinds.insert(Kind::Sequence);
        }
        kinds
    }

    /// The node's content under its sole evidenced kind: the checked
    /// projection, refusing a plural node instead of guessing.
    ///
    /// `Ok(None)` exactly when no kind is in evidence (the node is bottom,
    /// or holds only the ordering residue of superseded sequence content);
    /// `Ok(Some(content))` when exactly one kind is in evidence, handing out
    /// that kind's component even when it is bottom (tag present with bottom
    /// content *means* empty); an `Err` carrying [`KindPlurality`] when two
    /// or more kinds are in evidence, with the whole surfaced set inside. This is the
    /// read that retires the parallel-maps recipe's cross-kind hazard: a
    /// caller that only reads through `sole` cannot render a stale kind's
    /// subtree as if undisputed, and a caller resolving a plurality does so
    /// deliberately, off the raw component reads.
    ///
    /// # Errors
    ///
    /// [`KindPlurality`] carrying the evidenced set when it has two or more
    /// members.
    pub fn sole(&self) -> Result<Option<NodeContent<'_, K, V>>, KindPlurality> {
        let kinds = self.kinds_present();
        match kinds.sole() {
            Some(Kind::Register) => Ok(Some(NodeContent::Register(self.register()))),
            Some(Kind::Map) => Ok(Some(NodeContent::Map(self.children()))),
            Some(Kind::Sequence) => Ok(Some(NodeContent::Sequence(self.sequence()))),
            None if kinds.is_empty() => Ok(None),
            None => Err(KindPlurality { kinds }),
        }
    }
}