247 lines
8.4 KiB
Rust
247 lines
8.4 KiB
Rust
use super::clojure::{Parent2NodeSetterClojure, ParentProviderClojure};
|
|
use crate::BinaryTreeDirection;
|
|
use crate::NodeRefContainer;
|
|
use crate::context::{BinaryTreeParentSetterContext, BinaryTreeRootGetter};
|
|
use crate::context::BinaryTreeRootSetter;
|
|
use crate::context::{BinaryTreeChildrenGetterContext, BinaryTreeChildrenSetterContext};
|
|
use crate::directed::{
|
|
DirectedBinaryTreeChildrenGetterContext, DirectedBinaryTreeChildrenSetterContext,
|
|
};
|
|
use crate::direction::DirectedBinaryTreeDirection;
|
|
use crate::parent2node::clojure::Parent2NodeGetterClojure;
|
|
use std::mem::ManuallyDrop;
|
|
use std::ops::Deref;
|
|
|
|
macro_rules! _mut_switch {
|
|
($macro:tt $excl_mark:tt ( $($args:tt)+) ) => {
|
|
$macro$excl_mark($($args)+);
|
|
$macro$excl_mark($($args)+ mut);
|
|
};
|
|
}
|
|
|
|
union _NodeOrNothing<NodeRef> {
|
|
nothing: (),
|
|
node: ManuallyDrop<NodeRef>,
|
|
}
|
|
|
|
struct DynamicParent2NodeGetterClojureFromContext<CtxRef, NodeRef> {
|
|
dir: Option<BinaryTreeDirection>,
|
|
ctx: CtxRef,
|
|
node: _NodeOrNothing<NodeRef>,
|
|
}
|
|
|
|
struct DynamicParent2NodeGetterClojureFromDirectedContext<CtxRef, NodeRef> {
|
|
dir: Option<DirectedBinaryTreeDirection>,
|
|
ctx: CtxRef,
|
|
node: _NodeOrNothing<NodeRef>,
|
|
}
|
|
|
|
macro_rules! _constructor {
|
|
($name:ident $direction:ident) => {
|
|
impl<'ctx, Ctx: NodeRefContainer> $name <&'ctx Ctx, Ctx::NodeRef> {
|
|
pub fn wrapNode(
|
|
ctx: &'ctx Ctx, node: Ctx::NodeRef, direction: $direction
|
|
) -> Self {
|
|
return Self {
|
|
dir: Some(direction),
|
|
ctx: ctx,
|
|
node: _NodeOrNothing { node: ManuallyDrop::new(node) }
|
|
};
|
|
}
|
|
|
|
pub fn wrapRoot(
|
|
ctx: &'ctx Ctx
|
|
) -> Self {
|
|
return Self {
|
|
dir: None,
|
|
ctx: ctx,
|
|
node: _NodeOrNothing { nothing: () }
|
|
};
|
|
}
|
|
}
|
|
};
|
|
($name:ident $direction:ident mut) => {
|
|
impl<'ctx, Ctx: NodeRefContainer> $name <&'ctx mut Ctx, Ctx::NodeRef> {
|
|
pub fn wrapNode_mut(
|
|
ctx: &'ctx mut Ctx, node: Ctx::NodeRef, direction: $direction
|
|
) -> Self {
|
|
return Self {
|
|
dir: Some(direction),
|
|
ctx: ctx,
|
|
node: _NodeOrNothing { node: ManuallyDrop::new(node) }
|
|
};
|
|
}
|
|
|
|
pub fn wrapRoot_mut(
|
|
ctx: &'ctx mut Ctx
|
|
) -> Self {
|
|
return Self {
|
|
dir: None,
|
|
ctx: ctx,
|
|
node: _NodeOrNothing { nothing: () }
|
|
};
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
_mut_switch!(_constructor!(DynamicParent2NodeGetterClojureFromContext BinaryTreeDirection));
|
|
_mut_switch!(_constructor!(DynamicParent2NodeGetterClojureFromDirectedContext DirectedBinaryTreeDirection));
|
|
|
|
macro_rules! _node_ref {
|
|
($name:ident $($mut:tt)?) => {
|
|
impl<Ctx: NodeRefContainer> NodeRefContainer for $name<& $($mut)? Ctx, Ctx::NodeRef> {
|
|
type NodeRef = Ctx::NodeRef;
|
|
}
|
|
};
|
|
}
|
|
|
|
_mut_switch!(_node_ref!(DynamicParent2NodeGetterClojureFromContext));
|
|
_mut_switch!(_node_ref!(DynamicParent2NodeGetterClojureFromDirectedContext));
|
|
|
|
macro_rules! _get_child {
|
|
(
|
|
$name:ident $ctx_constraint:ident
|
|
$dir_enum_lbl:ident $d1_lbl:ident $d1_get:ident $d2_lbl:ident $d2_get:ident
|
|
$($mut:tt)?
|
|
) => {
|
|
impl<
|
|
'ctx,
|
|
Ctx: NodeRefContainer + BinaryTreeRootGetter + $ctx_constraint
|
|
> Parent2NodeGetterClojure
|
|
for $name <&'ctx $($mut)? Ctx, Ctx::NodeRef>
|
|
{
|
|
fn getChild(&self) -> Option<Self::NodeRef> {
|
|
match self.dir {
|
|
None => return self.ctx.getRoot(),
|
|
Some($dir_enum_lbl::$d1_lbl) => unsafe {
|
|
self.ctx.$d1_get ((*self.node.node.deref()).clone())
|
|
},
|
|
Some($dir_enum_lbl::$d2_lbl) => unsafe {
|
|
self.ctx.$d2_get ((*self.node.node.deref()).clone())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
_mut_switch!(_get_child!(
|
|
DynamicParent2NodeGetterClojureFromContext BinaryTreeChildrenGetterContext
|
|
BinaryTreeDirection LEFT getLeftChild RIGHT getRightChild
|
|
));
|
|
_mut_switch!(_get_child!(
|
|
DynamicParent2NodeGetterClojureFromDirectedContext DirectedBinaryTreeChildrenGetterContext
|
|
DirectedBinaryTreeDirection FORWARD getForwardChild OPPOSITE getOppositeChild
|
|
));
|
|
|
|
macro_rules! _set_child {
|
|
(
|
|
$name:ident $ctx_constraint:ident $dir_enum_lbl:ident
|
|
$d1_lbl:ident $d1_xset:ident $d1_set:ident $d1_clear:ident
|
|
$d2_lbl:ident $d2_xset:ident $d2_set:ident $d2_clear:ident
|
|
) => {
|
|
impl<
|
|
'ctx,
|
|
Ctx: NodeRefContainer + BinaryTreeRootSetter + $ctx_constraint
|
|
> Parent2NodeSetterClojure
|
|
for $name <&'ctx mut Ctx, Ctx::NodeRef>
|
|
{
|
|
fn xSetChild(&mut self, newChild: Option<Self::NodeRef>) {
|
|
match self.dir {
|
|
None => self.ctx.xSetRoot(newChild),
|
|
Some($dir_enum_lbl::$d1_lbl) => unsafe {
|
|
self.ctx.$d1_xset ((*self.node.node.deref()).clone(), newChild)
|
|
},
|
|
Some($dir_enum_lbl::$d2_lbl) => unsafe {
|
|
self.ctx.$d2_xset ((*self.node.node.deref()).clone(), newChild)
|
|
}
|
|
};
|
|
}
|
|
|
|
fn setChild(&mut self, newChild: Self::NodeRef) {
|
|
match self.dir {
|
|
None => self.ctx.setRoot(newChild),
|
|
Some($dir_enum_lbl::$d1_lbl) => unsafe {
|
|
self.ctx.$d1_set ((*self.node.node.deref()).clone(), newChild)
|
|
},
|
|
Some($dir_enum_lbl::$d2_lbl) => unsafe {
|
|
self.ctx.$d2_set ((*self.node.node.deref()).clone(), newChild)
|
|
}
|
|
};
|
|
}
|
|
|
|
fn clearChild(&mut self) {
|
|
match self.dir {
|
|
None => self.ctx.clearRoot(),
|
|
Some($dir_enum_lbl::$d1_lbl) => unsafe {
|
|
self.ctx.$d1_clear ((*self.node.node.deref()).clone())
|
|
},
|
|
Some($dir_enum_lbl::$d2_lbl) => unsafe {
|
|
self.ctx.$d2_clear ((*self.node.node.deref()).clone())
|
|
}
|
|
};
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
_set_child!(
|
|
DynamicParent2NodeGetterClojureFromContext
|
|
BinaryTreeChildrenSetterContext BinaryTreeDirection
|
|
LEFT xSetLeftChild setLeftChild clearLeftChild
|
|
RIGHT xSetRightChild setRightChild clearRightChild
|
|
);
|
|
_set_child!(
|
|
DynamicParent2NodeGetterClojureFromDirectedContext
|
|
DirectedBinaryTreeChildrenSetterContext DirectedBinaryTreeDirection
|
|
FORWARD xSetForwardChild setForwardChild clearForwardChild
|
|
OPPOSITE xSetOppositeChild setOppositeChild clearOppositeChild
|
|
);
|
|
|
|
|
|
macro_rules! _set_as_parent_of {
|
|
($name:ident $dir_enum_lbl:ident $d1_lbl:ident $d2_lbl:ident) => {
|
|
impl<'ctx, Ctx: BinaryTreeParentSetterContext> ParentProviderClojure
|
|
for $name<&'ctx mut Ctx, Ctx::NodeRef>
|
|
{
|
|
fn setAsParentOf(&mut self, child: Self::NodeRef) {
|
|
match self.dir {
|
|
None => self.ctx.clearParent(child),
|
|
Some($dir_enum_lbl::$d1_lbl) => unsafe {
|
|
self.ctx.setParent(child, (*self.node.node.deref()).clone())
|
|
},
|
|
Some($dir_enum_lbl::$d2_lbl) => unsafe {
|
|
self.ctx.setParent(child, (*self.node.node.deref()).clone())
|
|
}
|
|
};
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
_set_as_parent_of!(
|
|
DynamicParent2NodeGetterClojureFromContext
|
|
BinaryTreeDirection LEFT RIGHT
|
|
);
|
|
_set_as_parent_of!(
|
|
DynamicParent2NodeGetterClojureFromDirectedContext
|
|
DirectedBinaryTreeDirection FORWARD OPPOSITE
|
|
);
|
|
|
|
macro_rules! _drop {
|
|
($name:ident $($mut:tt)?) => {
|
|
impl<CtxRef, NodeRef> Drop for $name<CtxRef, NodeRef> {
|
|
fn drop(&mut self) {
|
|
if matches!(self.dir, Some(_)) {
|
|
unsafe { ManuallyDrop::drop(&mut self.node.node) }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
_drop!(DynamicParent2NodeGetterClojureFromContext);
|
|
_drop!(DynamicParent2NodeGetterClojureFromDirectedContext);
|
|
|