use crate::node::{Direction, Node, StaticNode};
use crate::options::{self, EipsOptions};
use core::cmp::Ordering;
use core::fmt;
use core::marker::PhantomData;
use skippy::{LeafNext, LeafRef, This};
use tagged_pointer::TaggedPtr;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum SiblingSetNodeKind {
Child = 0,
Parent = 1,
}
impl SiblingSetNodeKind {
pub const VARIANTS: [Self; 2] = [Self::Child, Self::Parent];
}
pub struct SiblingSetNext<Id, Opt: EipsOptions>(
TaggedPtr<Node<Id, Opt>, 2>,
PhantomData<StaticNode<Id, Opt>>,
);
impl<Id, Opt> SiblingSetNext<Id, Opt>
where
Opt: EipsOptions,
{
pub fn new(next: LeafNext<SiblingSetNode<Id, Opt>>) -> Self {
let (ptr, tag) = match next {
LeafNext::Data(data) => {
(data.cast(), SiblingSetNodeKind::VARIANTS.len())
}
LeafNext::Leaf(leaf) => (leaf.node().ptr(), leaf.kind() as usize),
};
Self(TaggedPtr::new(ptr, tag), PhantomData)
}
pub fn get(&self) -> LeafNext<SiblingSetNode<Id, Opt>> {
let (ptr, tag) = self.0.get();
if tag == SiblingSetNodeKind::VARIANTS.len() {
LeafNext::Data(ptr.cast())
} else {
LeafNext::Leaf(SiblingSetNode::new(
unsafe { StaticNode::new(ptr) },
SiblingSetNodeKind::VARIANTS[tag],
))
}
}
}
impl<Id, Opt> Clone for SiblingSetNext<Id, Opt>
where
Opt: EipsOptions,
{
fn clone(&self) -> Self {
*self
}
}
impl<Id, Opt: EipsOptions> Copy for SiblingSetNext<Id, Opt> {}
impl<Id, Opt> fmt::Debug for SiblingSetNext<Id, Opt>
where
Id: PartialEq + fmt::Debug,
Opt: EipsOptions,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("SiblingSetNext").field(&self.get()).finish()
}
}
pub struct Token(());
pub struct SiblingSetNode<Id, Opt: EipsOptions>(
TaggedPtr<Node<Id, Opt>, 1>,
PhantomData<StaticNode<Id, Opt>>,
);
impl<Id, Opt> SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
pub fn new(node: StaticNode<Id, Opt>, kind: SiblingSetNodeKind) -> Self {
Self(TaggedPtr::new(node.ptr(), kind as usize), PhantomData)
}
pub fn kind(&self) -> SiblingSetNodeKind {
SiblingSetNodeKind::VARIANTS[self.0.tag()]
}
pub fn node(&self) -> StaticNode<Id, Opt> {
unsafe { StaticNode::new(self.0.ptr()) }
}
pub fn as_node(&self) -> &Node<Id, Opt> {
unsafe { self.node().ptr().as_ref() }
}
pub fn key(&self) -> SiblingSetKey<&Id>
where
Id: PartialEq,
{
match self.kind() {
SiblingSetNodeKind::Child => SiblingSetKey::Child {
id: &self.as_node().id,
parent: self.as_node().parent(),
direction: self.as_node().direction(),
},
SiblingSetNodeKind::Parent => {
SiblingSetKey::Parent(&self.as_node().id)
}
}
}
}
unsafe impl<Id, Opt> LeafRef for SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
type Options = options::SiblingSetOptions<Id, Opt>;
fn next(&self) -> Option<LeafNext<Self>> {
self.node().sibling_set_next(Token(()))[self.kind() as usize]
.get()
.map(|n| n.get())
}
fn set_next(this: This<&'_ Self>, next: Option<LeafNext<Self>>) {
this.node().sibling_set_next(Token(()))[this.kind() as usize]
.set(next.map(SiblingSetNext::new))
}
}
impl<Id, Opt> Clone for SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
fn clone(&self) -> Self {
*self
}
}
impl<Id, Opt: EipsOptions> Copy for SiblingSetNode<Id, Opt> {}
impl<Id, Opt> PartialEq for SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<Id, Opt: EipsOptions> Eq for SiblingSetNode<Id, Opt> {}
impl<Id: Ord, Opt> PartialOrd for SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<Id: Ord, Opt> Ord for SiblingSetNode<Id, Opt>
where
Opt: EipsOptions,
{
fn cmp(&self, other: &Self) -> Ordering {
self.key().cmp(&other.key())
}
}
impl<Id, Opt> fmt::Debug for SiblingSetNode<Id, Opt>
where
Id: PartialEq + fmt::Debug,
Opt: EipsOptions,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("SiblingSetNode")
.field("kind", &self.kind())
.field("node", &self.node())
.finish()
}
}
#[derive(Clone, Copy)]
pub enum SiblingSetKey<Id> {
Child {
id: Id,
parent: Option<Id>,
direction: Direction,
},
Parent(Id),
}
impl<Id: Ord> PartialEq for SiblingSetKey<Id> {
fn eq(&self, other: &Self) -> bool {
self.cmp(other).is_eq()
}
}
impl<Id: Ord> Eq for SiblingSetKey<Id> {}
impl<Id: Ord> PartialOrd for SiblingSetKey<Id> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<Id: Ord> Ord for SiblingSetKey<Id> {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(
Self::Child {
id: id1,
parent: parent1,
direction: dir1,
},
Self::Child {
id: id2,
parent: parent2,
direction: dir2,
},
) => (parent1, dir1, id1).cmp(&(parent2, dir2, id2)),
(
Self::Child {
parent,
direction,
..
},
Self::Parent(id),
) => {
let ord = parent.as_ref().cmp(&Some(id));
if ord.is_ne() {
return ord;
}
match direction {
Direction::Before => Ordering::Less,
Direction::After => Ordering::Greater,
}
}
(
Self::Parent(id),
Self::Child {
parent,
direction,
..
},
) => {
let ord = Some(id).cmp(&parent.as_ref());
if ord.is_ne() {
return ord;
}
match direction {
Direction::Before => Ordering::Greater,
Direction::After => Ordering::Less,
}
}
(Self::Parent(id1), Self::Parent(id2)) => id1.cmp(id2),
}
}
}
impl<Id, Opt> PartialEq<SiblingSetKey<&Id>> for SiblingSetNode<Id, Opt>
where
Id: Ord,
Opt: EipsOptions,
{
fn eq(&self, other: &SiblingSetKey<&Id>) -> bool {
self.key() == *other
}
}
impl<Id, Opt> PartialEq<SiblingSetNode<Id, Opt>> for SiblingSetKey<&Id>
where
Id: Ord,
Opt: EipsOptions,
{
fn eq(&self, other: &SiblingSetNode<Id, Opt>) -> bool {
*self == other.key()
}
}
impl<Id, Opt> PartialOrd<SiblingSetKey<&Id>> for SiblingSetNode<Id, Opt>
where
Id: Ord,
Opt: EipsOptions,
{
fn partial_cmp(&self, other: &SiblingSetKey<&Id>) -> Option<Ordering> {
Some(self.key().cmp(other))
}
}
impl<Id, Opt> PartialOrd<SiblingSetNode<Id, Opt>> for SiblingSetKey<&Id>
where
Id: Ord,
Opt: EipsOptions,
{
fn partial_cmp(
&self,
other: &SiblingSetNode<Id, Opt>,
) -> Option<Ordering> {
Some(self.cmp(&other.key()))
}
}