#![allow(clippy::module_name_repetitions)]
use std::boxed::Box;
use std::rc::Rc;
use std::sync::Arc;
use std::ops::{Deref, DerefMut};
#[doc(no_inline)]
pub use kul_core::datum::{*, premade::*};
pub type BoxDatum<TT, ET> = Datum<TT, ET, DatumBox<TT, ET>>;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct DatumBox<TT, ET>(pub Box<BoxDatum<TT, ET>>);
impl<TT, ET> DatumBox<TT, ET> {
pub fn new(val: BoxDatum<TT, ET>) -> Self {
Self(Box::new(val))
}
}
impl<TT, ET> Deref for DatumBox<TT, ET> {
type Target = BoxDatum<TT, ET>;
fn deref(&self) -> &Self::Target {
Deref::deref(&self.0)
}
}
impl<TT, ET> DerefMut for DatumBox<TT, ET> {
fn deref_mut(&mut self) -> &mut Self::Target {
DerefMut::deref_mut(&mut self.0)
}
}
impl<TT, ET> DerefTryMut for DatumBox<TT, ET> {
fn get_mut(this: &mut Self) -> Option<&mut Self::Target> {
Some(DerefMut::deref_mut(this))
}
}
pub type RcDatum<TT, ET> = Datum<TT, ET, DatumRc<TT, ET>>;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct DatumRc<TT, ET>(pub Rc<RcDatum<TT, ET>>);
impl<TT, ET> DatumRc<TT, ET> {
pub fn new(val: RcDatum<TT, ET>) -> Self {
Self(Rc::new(val))
}
}
impl<TT, ET> Deref for DatumRc<TT, ET> {
type Target = RcDatum<TT, ET>;
fn deref(&self) -> &Self::Target {
Deref::deref(&self.0)
}
}
impl<TT, ET> DerefTryMut for DatumRc<TT, ET> {
fn get_mut(this: &mut Self) -> Option<&mut Self::Target> {
Rc::get_mut(&mut this.0)
}
}
pub type ArcDatum<TT, ET> = Datum<TT, ET, DatumArc<TT, ET>>;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct DatumArc<TT, ET>(pub Arc<ArcDatum<TT, ET>>);
impl<TT, ET> DatumArc<TT, ET> {
pub fn new(val: ArcDatum<TT, ET>) -> Self {
Self(Arc::new(val))
}
}
impl<TT, ET> Deref for DatumArc<TT, ET> {
type Target = ArcDatum<TT, ET>;
fn deref(&self) -> &Self::Target {
Deref::deref(&self.0)
}
}
impl<TT, ET> DerefTryMut for DatumArc<TT, ET> {
fn get_mut(this: &mut Self) -> Option<&mut Self::Target> {
Arc::get_mut(&mut this.0)
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::enum_glob_use)]
use super::*;
use kul_shared_tests::utils::tree_shapes::*;
use Datum::*;
#[derive(Copy, Clone, PartialEq, Debug)]
struct DummyText;
#[test]
fn ref_equality_same() {
assert_eq!(DatumBox::new(EmptyNest::<DummyText, u32, _>),
DatumBox::new(EmptyNest::<_, _, _>));
assert_ne!(DatumBox::new(EmptyNest::<DummyText, (), _>),
DatumBox::new(EmptyList::<_, _, _>));
assert_eq!(DatumRc::new(EmptyNest::<DummyText, bool, _>),
DatumRc::new(EmptyNest::<_, _, _>));
assert_ne!(DatumRc::new(EmptyNest::<DummyText, (), _>),
DatumRc::new(EmptyList::<_, _, _>));
assert_eq!(DatumArc::new(EmptyNest::<DummyText, char, _>),
DatumArc::new(EmptyNest::<_, _, _>));
assert_ne!(DatumArc::new(EmptyNest::<DummyText, (), _>),
DatumArc::new(EmptyList::<_, _, _>));
}
#[test]
fn equality_diff_ref() {
assert_eq!(*DatumBox::new(EmptyNest::<DummyText, u32, _>),
*DatumRc::new(EmptyNest::<DummyText, u32, _>));
assert_eq!(*DatumBox::new(EmptyNest::<DummyText, f64, _>),
*DatumArc::new(EmptyNest::<DummyText, f64, _>));
assert_eq!(*DatumBox::new(EmptyList::<DummyText, bool, _>),
*DatumRc::new(EmptyList::<DummyText, bool, _>));
assert_ne!(*DatumArc::new(EmptyList::<DummyText, i128, _>),
*DatumRc::new(EmptyNest::<DummyText, i128, _>));
assert_eq!(*DatumBox::new(List::<DummyText, _, _>{
elem: DatumBox::new(Extra('λ')),
next: DatumBox::new(EmptyList)}),
*DatumRc::new(List::<DummyText, _, _>{
elem: DatumRc::new(Extra('λ')),
next: DatumRc::new(EmptyList)}));
}
#[test]
fn clone() {
let a = List::<DummyText, (), _>{
elem: DatumBox::new(EmptyNest::<_, _, _>),
next: DatumBox::new(EmptyList::<_, _, _>)};
let b = a.clone();
assert_eq!(a, b);
let c = List::<DummyText, (), _>{
elem: DatumRc::new(EmptyNest::<_, _, _>),
next: DatumRc::new(EmptyList::<_, _, _>)};
let d = c.clone();
assert_eq!(c, d);
let e = List::<DummyText, (), _>{
elem: DatumArc::new(EmptyNest::<_, _, _>),
next: DatumArc::new(EmptyList::<_, _, _>)};
let f = e.clone();
assert_eq!(e, f);
}
#[test]
fn deep_list_equality() {
let len = list_len(get_arg_tree_size());
let boxes = make_box_list(len);
assert_eq!(boxes, boxes);
let rcs = make_rc_list(len);
assert_eq!(rcs, rcs);
let arcs = make_arc_list(len);
assert_eq!(arcs, arcs);
assert_eq!(*boxes, *rcs);
assert_eq!(*boxes, *arcs);
assert_eq!(*rcs, *arcs);
}
#[test]
fn deep_nest_equality() {
let depth = nest_depth(get_arg_tree_size());
let boxes = make_box_nest(depth);
assert_eq!(boxes, boxes);
let rcs = make_rc_nest(depth);
assert_eq!(rcs, rcs);
let arcs = make_arc_nest(depth);
assert_eq!(arcs, arcs);
assert_eq!(*boxes, *rcs);
assert_eq!(*boxes, *arcs);
assert_eq!(*rcs, *arcs);
}
#[test]
fn deep_zigzag_equality() {
let depth = zigzag_depth(get_arg_tree_size());
let boxes = make_box_zigzag(depth);
assert_eq!(boxes, boxes);
let rcs = make_rc_zigzag(depth);
assert_eq!(rcs, rcs);
let arcs = make_arc_zigzag(depth);
assert_eq!(arcs, arcs);
assert_eq!(*boxes, *rcs);
assert_eq!(*boxes, *arcs);
assert_eq!(*rcs, *arcs);
}
#[test]
#[ignore]
fn deep_unusual_zigzag_equality_overflow()
{
use kul_shared_tests::TestStrText;
fn make_unusual_zigzag(depth: usize) -> DatumBox<TestStrText, usize> {
make_zigzag(depth, &DatumBox::new,
|| EmptyNest,
|elem, next| List{elem, next},
|operator, operands| Combination{operator, operands},
|cnt, new| new(Extra(cnt)),
|_, new| new(EmptyList))
}
let depth = zigzag_depth(get_arg_tree_size());
let boxes = make_unusual_zigzag(depth);
assert_eq!(boxes, boxes);
}
#[test]
fn deep_fan_equality() {
let depth = fan_depth(get_arg_tree_size());
let boxes = make_box_fan(depth);
assert_eq!(boxes, boxes);
let rcs = make_rc_fan(depth);
assert_eq!(rcs, rcs);
let arcs = make_arc_fan(depth);
assert_eq!(arcs, arcs);
assert_eq!(*boxes, *rcs);
assert_eq!(*boxes, *arcs);
assert_eq!(*rcs, *arcs);
}
#[test]
fn deep_vee_equality() {
let half_size = get_arg_tree_size() / 2;
let (left_depth, right_depth) = vee_depths(half_size, half_size);
let boxes = make_box_vee(left_depth, right_depth);
assert_eq!(boxes, boxes);
let rcs = make_rc_vee(left_depth, right_depth);
assert_eq!(rcs, rcs);
let arcs = make_arc_vee(left_depth, right_depth);
assert_eq!(arcs, arcs);
assert_eq!(*boxes, *rcs);
assert_eq!(*boxes, *arcs);
assert_eq!(*rcs, *arcs);
}
}