use std::{cmp::Ordering, fmt::Display, hash::Hash};
use crate::class_mapping::{Leader, RevisionNESet};
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Copy, Clone, Ord)]
pub enum Revision {
Base,
Left,
Right,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum PCSNode<'a> {
VirtualRoot,
LeftMarker,
Node {
revisions: RevisionNESet,
node: Leader<'a>,
},
RightMarker,
}
#[derive(Debug, Copy, Clone, PartialOrd, Ord)]
#[allow(clippy::upper_case_acronyms)]
pub struct PCS<'a> {
pub parent: PCSNode<'a>,
pub predecessor: PCSNode<'a>,
pub successor: PCSNode<'a>,
pub revision: Revision,
}
impl PartialEq for PCS<'_> {
fn eq(&self, other: &Self) -> bool {
self.parent == other.parent
&& self.predecessor == other.predecessor
&& self.successor == other.successor
}
}
impl Eq for PCS<'_> {}
impl Hash for PCS<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.parent.hash(state);
self.predecessor.hash(state);
self.successor.hash(state);
}
}
impl Display for PCSNode<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PCSNode::VirtualRoot => write!(f, "⊥"),
PCSNode::LeftMarker => write!(f, "⊣"),
PCSNode::Node { node: rn, .. } => write!(f, "{rn}"),
PCSNode::RightMarker => write!(f, "⊢"),
}
}
}
impl Ord for PCSNode<'_> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
#[allow(clippy::match_same_arms)]
match (self, other) {
(PCSNode::VirtualRoot, PCSNode::VirtualRoot) => Ordering::Equal,
(PCSNode::VirtualRoot, _) => Ordering::Less,
(_, PCSNode::VirtualRoot) => Ordering::Greater,
(PCSNode::LeftMarker, PCSNode::LeftMarker) => Ordering::Equal,
(PCSNode::LeftMarker, _) => Ordering::Less,
(_, PCSNode::LeftMarker) => Ordering::Greater,
(PCSNode::RightMarker, PCSNode::RightMarker) => Ordering::Equal,
(PCSNode::RightMarker, _) => Ordering::Greater,
(_, PCSNode::RightMarker) => Ordering::Less,
(PCSNode::Node { node: leader_a, .. }, PCSNode::Node { node: leader_b, .. }) => {
let a = leader_a.as_representative().node;
let b = leader_b.as_representative().node;
let key_a = (
a.byte_range.start,
a.byte_range.start as i32 - (a.byte_range.end as i32),
-a.height(),
);
let key_b = (
b.byte_range.start,
b.byte_range.start as i32 - (b.byte_range.end as i32),
-b.height(),
);
key_a.cmp(&key_b)
}
}
}
}
impl PartialOrd for PCSNode<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl Display for Revision {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Base => "Base",
Self::Left => "Left",
Self::Right => "Right",
})
}
}
impl Display for PCS<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"({}, {}, {}, {})",
self.parent, self.predecessor, self.successor, self.revision
)
}
}