extern crate alloc;
use alloc::collections::BTreeMap;
use super::DotSet;
mod ancestry;
mod children;
mod condense;
mod extent;
mod identity;
mod maintenance;
mod placement;
mod possession;
mod recension;
mod refound;
mod reparent;
mod store;
mod thread;
mod traversal;
mod wire;
#[cfg(feature = "instrumentation")]
pub use ancestry::AncestryProfile;
pub use ancestry::{
AncestryQueryError, AncestryRelation, CoordinateError as AncestryCoordinateError,
};
use children::ChildPlane;
pub use extent::{Extent, Verge};
use identity::IdentityPlane;
use placement::Dot;
pub use placement::{Anchor, Locus};
use possession::OccupancyPlane;
#[cfg(feature = "instrumentation")]
pub use recension::RecensionProfile;
pub use recension::{
AncestryAdmissionError, ExactAncestry, MovementBatch, MovementBatchError, Recension,
};
#[cfg(feature = "timing")]
pub use recension::{
MovementBatchMoveProfile, MovementCycleValidationProfile, MovementCycleValidationWork,
MovementTopologyPhases, MovementTopologyProfile, MovementTopologyWork, ProfiledMovement,
};
pub use refound::{
RefoundMap, RefoundMapDecodeBudget, RefoundMapDecodeError, Refounded, UnsealedStratum,
};
use reparent::PlacementEffect;
use thread::OrderThread;
pub use traversal::{OrderWalk, OrderWalkRev};
pub use wire::RhapsodyDecodeError;
pub use wire::SnapshotDecodeError;
#[cfg(feature = "instrumentation")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct RhapsodyProfile {
pub skeleton_dots: usize,
pub explicit_loci: usize,
pub placed_slots: usize,
pub order_fragments: usize,
pub visible_pages: usize,
pub visible_exceptions: usize,
pub woven_exceptions: usize,
}
#[cfg(any(test, kani))]
pub use wire::rank_successor;
#[derive(Clone, Debug, Default)]
pub struct Rhapsody {
skeleton: IdentityPlane,
visible: DotSet,
children: ChildPlane,
unplaced: alloc::collections::BTreeSet<Dot>,
woven: DotSet,
thread: OrderThread,
visible_pages: OccupancyPlane,
}
impl PartialEq for Rhapsody {
fn eq(&self, other: &Self) -> bool {
self.skeleton == other.skeleton && self.visible == other.visible
}
}
impl Eq for Rhapsody {}
impl core::hash::Hash for Rhapsody {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.skeleton.hash(state);
self.visible.hash(state);
}
}
impl Rhapsody {
#[must_use]
pub const fn new() -> Self {
Self {
skeleton: IdentityPlane::new(),
visible: DotSet::new(),
children: ChildPlane::new(),
unplaced: alloc::collections::BTreeSet::new(),
woven: DotSet::new(),
thread: OrderThread::new(),
visible_pages: OccupancyPlane::new(),
}
}
fn from_parts(skeleton: BTreeMap<Dot, Locus>, visible: DotSet) -> Self {
let mut plane = IdentityPlane::new();
plane.extend_ascending(skeleton);
Self::from_plane(plane, visible)
}
fn from_plane(skeleton: IdentityPlane, visible: DotSet) -> Self {
let children = ChildPlane::build(&skeleton);
let unplaced = Self::build_unplaced(&skeleton, &children);
let mut woven = DotSet::new();
for (dot, _) in skeleton.iter() {
let _ = woven.insert(dot);
}
let visible_pages = OccupancyPlane::from_pages(visible.occupancy_pages());
let mut built = Self {
skeleton,
visible,
children,
unplaced,
woven,
thread: OrderThread::new(),
visible_pages,
};
if !built.skeleton.is_empty() {
built.rebuild_thread();
}
built
}
#[must_use]
pub const fn woven(&self) -> &DotSet {
&self.woven
}
#[must_use]
pub fn locus(&self, dot: Dot) -> Option<Locus> {
self.skeleton.get(&dot)
}
#[must_use]
pub fn is_visible(&self, dot: Dot) -> bool {
self.visible.contains(dot)
}
#[must_use]
pub fn visible_len(&self) -> usize {
self.visible.dots().count()
}
#[must_use]
pub const fn skeleton_len(&self) -> usize {
self.skeleton.len()
}
#[cfg(feature = "instrumentation")]
#[must_use]
pub fn profile(&self) -> RhapsodyProfile {
RhapsodyProfile {
skeleton_dots: self.skeleton.len(),
explicit_loci: self.skeleton_explicit_entries(),
placed_slots: self.thread.slot_len(),
order_fragments: self.order_thread_fragments(),
visible_pages: self.visible_pages.page_count(),
visible_exceptions: self.visible.exceptions_len(),
woven_exceptions: self.woven.exceptions_len(),
}
}
#[cfg(any(test, feature = "instrumentation"))]
pub(crate) const fn skeleton_explicit_entries(&self) -> usize {
self.skeleton.explicit_entries()
}
#[cfg(test)]
pub(crate) fn child_explicit_buckets(&self) -> usize {
self.children.explicit_buckets()
}
#[cfg(test)]
pub(crate) fn child_explicit_children(&self) -> usize {
self.children.explicit_children()
}
#[cfg(any(test, feature = "instrumentation"))]
pub(crate) fn order_thread_fragments(&self) -> usize {
self.thread.fragments()
}
#[cfg(test)]
pub(crate) fn order_thread_region_nodes(&self) -> usize {
self.thread.region_nodes()
}
#[cfg(test)]
pub(crate) fn order_thread_region_segments(&self) -> usize {
self.thread.region_segments()
}
#[cfg(test)]
pub(crate) fn order_thread_region_forest_nodes(&self) -> usize {
self.thread.region_forest_nodes()
}
#[cfg(test)]
pub(crate) fn check_order_thread(&self) {
self.thread.check_invariants();
assert_eq!(
self.thread.region_nodes(),
self.thread.slot_len(),
"the region segments cover every placed slot exactly once"
);
self.visible_pages.check_against(self.visible.dots());
}
#[must_use]
pub fn order_len(&self) -> usize {
self.thread.visible_len()
}
#[must_use]
pub fn order_at(&self, offset: usize) -> Option<Dot> {
self.thread.order_at(offset)
}
#[must_use]
pub fn offset_of(&self, dot: Dot) -> Option<usize> {
self.thread
.position_of(dot)
.map(|(_, visible_before)| visible_before)
}
}