Dynamic wrapper for parent2node clojure
This commit is contained in:
parent
6ce69a3ad5
commit
02dcc7f13f
164
src/parent2node/dynamic_wrappers.rs
Normal file
164
src/parent2node/dynamic_wrappers.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use super::clojure::Parent2NodeSetterClojure;
|
||||
use crate::BinaryTreeDirection;
|
||||
use crate::NodeRefContainer;
|
||||
use crate::context::BinaryTreeRootGetter;
|
||||
use crate::context::{BinaryTreeChildrenGetterContext, BinaryTreeChildrenSetterContext};
|
||||
use crate::directed::{
|
||||
DirectedBinaryTreeChildrenGetterContext, DirectedBinaryTreeChildrenSetterContext,
|
||||
};
|
||||
use crate::direction::DirectedBinaryTreeDirection;
|
||||
use crate::parent2node::clojure::Parent2NodeGetterClojure;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
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 dyn_lr<CtxRef, NodeRef> {
|
||||
dir: Option<BinaryTreeDirection>,
|
||||
ctx: CtxRef,
|
||||
node: _NodeOrNothing<NodeRef>,
|
||||
}
|
||||
|
||||
struct dyn_dir<CtxRef, NodeRef> {
|
||||
dir: Option<DirectedBinaryTreeDirection>,
|
||||
ctx: CtxRef,
|
||||
node: _NodeOrNothing<NodeRef>,
|
||||
}
|
||||
|
||||
macro_rules! _constructor {
|
||||
($name:ident $direction:ident $($mut:tt)?) => {
|
||||
impl<'ctx, Ctx: NodeRefContainer> $name <&'ctx $($mut)? Ctx, Ctx::NodeRef> {
|
||||
pub fn wrap_not_root(
|
||||
ctx: &'ctx $($mut)? Ctx, node: Ctx::NodeRef, direction: $direction
|
||||
) -> Self {
|
||||
return Self {
|
||||
dir: Some(direction),
|
||||
ctx: ctx,
|
||||
node: _NodeOrNothing { node: ManuallyDrop::new(node) }
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_mut_switch!(_constructor!(dyn_lr BinaryTreeDirection));
|
||||
_mut_switch!(_constructor!(dyn_dir 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!(dyn_lr));
|
||||
_mut_switch!(_node_ref!(dyn_dir));
|
||||
|
||||
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) -> Self::NodeRef {
|
||||
match self.dir {
|
||||
None => return self.ctx.getRoot(),
|
||||
Some($dir_enum_lbl::$d1_lbl) => self.ctx.$d1_get (self.ctx.node.node),
|
||||
Some($dir_enum_lbl::$d2_lbl) => self.ctx.$d2_get (self.ctx.node.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_mut_switch!(_get_child!(
|
||||
dyn_lr BinaryTreeChildrenGetterContext
|
||||
BinaryTreeDirection LEFT getLeftChild RIGHT getRightChild
|
||||
));
|
||||
_mut_switch!(_get_child!(
|
||||
dyn_dir 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
|
||||
$($mut:tt)?
|
||||
) => {
|
||||
impl<
|
||||
'ctx,
|
||||
Ctx: NodeRefContainer + BinaryTreeRootGetter + $ctx_constraint
|
||||
> Parent2NodeSetterClojure
|
||||
for $name <&'ctx $($mut)? Ctx, Ctx::NodeRef>
|
||||
{
|
||||
fn xSetChild(&mut self, newChild: Option<Self::NodeRef>) {
|
||||
match self.dir {
|
||||
None => return self.ctx.xSetRoot(newChild),
|
||||
Some($dir_enum_lbl::$d1_lbl) => self.ctx.$d1_xset (self.ctx.node.node, newChild),
|
||||
Some($dir_enum_lbl::$d2_lbl) => self.ctx.$d2_xset (self.ctx.node.node, newChild)
|
||||
}
|
||||
}
|
||||
|
||||
fn setChild(&mut self, newChild: Self::NodeRef) {
|
||||
match self.dir {
|
||||
None => return self.ctx.setRoot(newChild),
|
||||
Some($dir_enum_lbl::$d1_lbl) => self.ctx.$d1_set (self.ctx.node.node, newChild),
|
||||
Some($dir_enum_lbl::$d2_lbl) => self.ctx.$d2_set (self.ctx.node.node, newChild)
|
||||
}
|
||||
}
|
||||
|
||||
fn clearChild(&mut self) {
|
||||
match self.dir {
|
||||
None => return self.ctx.clearRoot(),
|
||||
Some($dir_enum_lbl::$d1_lbl) => self.ctx.$d1_clear (self.ctx.node.node),
|
||||
Some($dir_enum_lbl::$d2_lbl) => self.ctx.$d2_clear (self.ctx.node.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_set_child!(
|
||||
dyn_lr BinaryTreeChildrenSetterContext BinaryTreeDirection
|
||||
LEFT xSetLeftChild setLeftChild clearLeftChild
|
||||
RIGHT xSetRightChild setRightChild clearRightChild
|
||||
);
|
||||
_set_child!(
|
||||
dyn_dir DirectedBinaryTreeChildrenSetterContext DirectedBinaryTreeDirection
|
||||
FORWARD xSetForwardChild setForwardChild clearForwardChild
|
||||
OPPOSITE xSetOppositeChild setOppositeChild clearOppositeChild
|
||||
);
|
||||
|
||||
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!(dyn_lr);
|
||||
_drop!(dyn_dir);
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
mod clojure;
|
||||
mod fixed_wrapper;
|
||||
mod fixed_wrapper;
|
||||
mod dynamic_wrappers;
|
||||
Loading…
Reference in New Issue
Block a user