display-node 0.1.0

Tiny crate adding a trait to display recursive structures like node trees.
Documentation
use std::{fmt::Display, mem::swap};

use crate::DisplayableNode;

pub struct BinaryTree<D> {
    data: D,
    children: [Option<Box<BinaryTree<D>>>; 2],
}
#[macro_export]
macro_rules! bt {
    (
 $value:expr,
 $left:expr,
 $right:expr
 ) => {{
        BinaryTree::assemble(($value), Some($left), Some($right))
    }};

    (
 $value:expr,
 ,
 $right:expr
 ) => {{
        BinaryTree::assemble(($value), None, Some($right))
    }};

    (
 $value:expr,
 $left:expr,

 ) => {{
        BinaryTree::assemble(($value), Some($left), None)
    }};

    (
 $value:expr
 ) => {{
        BinaryTree::new(($value))
    }};
}

impl<D> BinaryTree<D> {
    pub fn new(data: D) -> Self {
        Self {
            data,
            children: [None, None],
        }
    }

    pub fn assemble(data: D, x: Option<BinaryTree<D>>, y: Option<BinaryTree<D>>) -> Self {
        let x = x.map(|x| Box::new(x));
        let y = y.map(|y| Box::new(y));
        Self {
            data,
            children: [x, y],
        }
    }

    pub fn children(&self) -> (Option<&BinaryTree<D>>, Option<&BinaryTree<D>>) {
        let [x, y] = &self.children;
        let x = x.as_ref().map(|boxed_x| boxed_x.as_ref());
        let y = y.as_ref().map(|boxed_y| boxed_y.as_ref());
        (x, y)
    }

    pub fn x_ref(&self) -> Option<&BinaryTree<D>> {
        self.children[0].as_ref().map(|boxed| boxed.as_ref())
    }

    pub fn y_ref(&self) -> Option<&BinaryTree<D>> {
        self.children[1].as_ref().map(|boxed| boxed.as_ref())
    }

    pub fn x_mut(&mut self) -> Option<&mut BinaryTree<D>> {
        self.children[0].as_mut().map(|boxed| boxed.as_mut())
    }

    pub fn y_mut(&mut self) -> Option<&mut BinaryTree<D>> {
        self.children[1].as_mut().map(|boxed| boxed.as_mut())
    }

    pub fn set_x(&mut self, x: BinaryTree<D>) -> Option<BinaryTree<D>> {
        let mut outer = Some(Box::new(x));
        let outer_ref = &mut outer;
        let inner_ref = &mut self.children[0];
        swap(outer_ref, inner_ref);
        outer.map(|boxed| *boxed)
    }

    pub fn set_y(&mut self, y: BinaryTree<D>) -> Option<BinaryTree<D>> {
        let mut outer = Some(Box::new(y));
        let outer_ref = &mut outer;
        let inner_ref = &mut self.children[1];
        swap(outer_ref, inner_ref);
        outer.map(|boxed| *boxed)
    }

    pub fn data(&self) -> &D {
        &self.data
    }

    pub fn data_put(&mut self) -> &mut D {
        &mut self.data
    }
}

impl<D: Display> DisplayableNode for BinaryTree<D> {
    fn label(&self) -> Option<String> {
        let data = self.data();
        Some(format!("{data}"))
    }

    fn children(&self) -> Vec<&Self> {
        match self.children() {
            (Some(left), Some(right)) => vec![left, right],
            (Some(left), None) => vec![left],
            (None, Some(right)) => vec![right],
            (None, None) => vec![],
        }
    }
}

#[test]
fn it_works() {
    let tree = bt!(
        1,
        bt!(
            2,
            ,
            bt!(5)
        ),
        bt!(3, bt!(4, bt!(7),), bt!(6))
    );

    println!("{}", tree.display());
}