minerva 0.2.0

Causal ordering for distributed systems
//! Point and run mutation over the counted fragment arena.

extern crate alloc;

use alloc::vec::Vec;
use core::num::NonZeroU64;

use super::{Dot, Extraction, FRAG_CAP, Fragment, NIL, Node, NodeKind, OrderThread};

impl OrderThread {
    /// Sets visibility when `dot` has a placed slot.
    pub(in crate::metis::rhapsody) fn set_visible(&mut self, dot: Dot, visible: bool) -> bool {
        let Some((leaf, frag_position, offset)) = self.locate(dot) else {
            return false;
        };
        let NodeKind::Leaf(frags) = &mut self.nodes[leaf as usize].kind else {
            unreachable!("locate returns leaves only");
        };
        let bit = 1u64 << offset;
        if visible {
            frags[frag_position].visible |= bit;
        } else {
            frags[frag_position].visible &= !bit;
        }
        self.refresh_to_root(leaf);
        true
    }

    /// Sets visibility for every held slot in a contiguous dot run.
    pub(in crate::metis::rhapsody) fn set_visible_run(
        &mut self,
        station: u32,
        first: NonZeroU64,
        len: u32,
        visible: bool,
    ) {
        if len == 0 {
            return;
        }
        let last = first.get().saturating_add(u64::from(len) - 1);
        let mut cursor = first;
        loop {
            let covered = match self.locate(Dot::new(station, cursor)) {
                Some((leaf, frag_position, offset)) => {
                    let NodeKind::Leaf(frags) = &mut self.nodes[leaf as usize].kind else {
                        unreachable!("locate returns leaves only");
                    };
                    let frag = &mut frags[frag_position];
                    let span_end = frag.base.get() + u64::from(frag.len) - 1;
                    let covered = span_end.min(last) - cursor.get() + 1;
                    let width = u32::try_from(covered).expect("a fragment spans at most 64 dots");
                    let mask = if width == 64 {
                        u64::MAX
                    } else {
                        ((1u64 << width) - 1) << offset
                    };
                    if visible {
                        frag.visible |= mask;
                    } else {
                        frag.visible &= !mask;
                    }
                    self.refresh_to_root(leaf);
                    covered
                }
                None => 1,
            };
            match cursor.checked_add(covered) {
                Some(next) if next.get() <= last => cursor = next,
                _ => return,
            }
        }
    }

    /// Inserts `dot` at slot-space `position`.
    pub(in crate::metis::rhapsody) fn insert_slot(
        &mut self,
        position: usize,
        dot: Dot,
        visible: bool,
    ) {
        debug_assert!(position <= self.slot_len());
        if self.root == NIL {
            let leaf = self.alloc(Node {
                parent: NIL,
                slots: 1,
                visible: usize::from(visible),
                kind: NodeKind::Leaf(alloc::vec![Fragment::single(dot, visible)]),
            });
            self.root = leaf;
            let _ = self.index.insert(dot, leaf);
            return;
        }
        let (leaf, mut within) = self.leaf_at_slot(position);
        let NodeKind::Leaf(frags) = &mut self.nodes[leaf as usize].kind else {
            unreachable!("slot descent returns leaves only");
        };
        let mut frag_position = 0;
        while frag_position < frags.len() && within > frags[frag_position].slots() {
            within -= frags[frag_position].slots();
            frag_position += 1;
        }
        if frag_position < frags.len() && within == frags[frag_position].slots() {
            // Checked addition refuses a successor past the dot ceiling.
            let frag = &mut frags[frag_position];
            if frag.station == dot.station()
                && frag.base.checked_add(u64::from(frag.len)) == Some(dot.counter_nonzero())
                && frag.slots() < FRAG_CAP
            {
                if visible {
                    frag.visible |= 1u64 << frag.len;
                }
                frag.len += 1;
                self.refresh_to_root(leaf);
                return;
            }
            frag_position += 1;
            within = 0;
        }
        let fresh = Fragment::single(dot, visible);
        if within == 0 || frag_position >= frags.len() {
            frags.insert(frag_position.min(frags.len()), fresh);
        } else {
            let head = frags[frag_position];
            let cut = u8::try_from(within).expect("fragment offsets fit u8");
            let tail = Fragment {
                station: head.station,
                base: head.base.saturating_add(u64::from(cut)),
                len: head.len - cut,
                visible: head.visible >> cut,
            };
            frags[frag_position] = Fragment {
                visible: head.visible & ((1u64 << cut) - 1),
                len: cut,
                ..head
            };
            frags.insert(frag_position + 1, fresh);
            frags.insert(frag_position + 2, tail);
            let _ = self.index.insert(tail.base_dot(), leaf);
        }
        let _ = self.index.insert(dot, leaf);
        self.split_leaf_if_over(leaf);
        self.refresh_to_root(leaf);
    }

    /// Inserts a contiguous dot run at slot-space `position`.
    pub(in crate::metis::rhapsody) fn insert_run(
        &mut self,
        position: usize,
        station: u32,
        first: NonZeroU64,
        len: u32,
        visible: bool,
    ) {
        if len == 0 {
            return;
        }
        let mut frags: Vec<Fragment> = Vec::with_capacity((len as usize).div_ceil(FRAG_CAP));
        let mut base = first;
        let mut remaining = len as usize;
        while remaining > 0 {
            let take = remaining.min(FRAG_CAP);
            let mask = if !visible {
                0
            } else if take == FRAG_CAP {
                u64::MAX
            } else {
                (1u64 << take) - 1
            };
            frags.push(Fragment {
                station,
                base,
                len: u8::try_from(take).expect("a fragment holds at most FRAG_CAP slots"),
                visible: mask,
            });
            remaining -= take;
            if remaining > 0 {
                // Advance only when another fragment exists.
                base = base.saturating_add(take as u64);
            }
        }
        self.insert_fragments(position, Extraction { frags });
    }

    /// Removes `dot`'s slot when it is placed.
    pub(in crate::metis::rhapsody) fn remove_slot(&mut self, dot: Dot) -> bool {
        let Some((leaf, frag_position, offset)) = self.locate(dot) else {
            return false;
        };
        let NodeKind::Leaf(frags) = &mut self.nodes[leaf as usize].kind else {
            unreachable!("locate returns leaves only");
        };
        let frag = frags[frag_position];
        let _ = self.index.remove(&frag.base_dot());
        if frag.len == 1 {
            let _ = frags.remove(frag_position);
            if frags.is_empty() {
                self.detach_empty(leaf);
            } else {
                self.refresh_to_root(leaf);
            }
            return true;
        }
        let cut = u8::try_from(offset).expect("fragment offsets fit u8");
        let below = (1u64 << cut) - 1;
        if cut == 0 {
            let rebased = Fragment {
                station: frag.station,
                base: frag.base.saturating_add(1),
                len: frag.len - 1,
                visible: frag.visible >> 1,
            };
            frags[frag_position] = rebased;
            let _ = self.index.insert(rebased.base_dot(), leaf);
        } else if cut == frag.len - 1 {
            let truncated = Fragment {
                len: frag.len - 1,
                visible: frag.visible & below,
                ..frag
            };
            frags[frag_position] = truncated;
            let _ = self.index.insert(truncated.base_dot(), leaf);
        } else {
            let head = Fragment {
                len: cut,
                visible: frag.visible & below,
                ..frag
            };
            let tail = Fragment {
                station: frag.station,
                base: frag.base.saturating_add(u64::from(cut) + 1),
                len: frag.len - cut - 1,
                visible: frag.visible >> (cut + 1),
            };
            frags[frag_position] = head;
            frags.insert(frag_position + 1, tail);
            let _ = self.index.insert(head.base_dot(), leaf);
            let _ = self.index.insert(tail.base_dot(), leaf);
            self.split_leaf_if_over(leaf);
        }
        self.refresh_to_root(leaf);
        true
    }
}