use std::fmt::{Debug, Display}; use crate::board::TreeElement; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TreeDir { Right, Left, This, } #[derive(Clone, Copy)] pub struct TreeCoords { len: usize, coords: [TreeDir; 4], inversion: [bool; 4], } impl Display for TreeCoords { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.is_inverted() { write!(f, "-")? } else { write!(f, "+")? } for c in self.coords { match c { TreeDir::Left => write!(f, "L")?, TreeDir::Right => write!(f, "R")?, TreeDir::This => break, } } Ok(()) } } impl Debug for TreeCoords { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(self, f) } } #[allow(dead_code)] impl TreeCoords { pub fn new() -> Self { Self { len: 0, coords: [TreeDir::This; 4], inversion: [false; 4], } } pub fn push(&mut self, dir: TreeDir, invert: bool) { if self.len == 4 || dir == TreeDir::This { return; } self.coords[self.len] = dir; self.inversion[self.len] = invert; self.len += 1; } pub fn pop(&mut self) -> Option<(TreeDir, bool)> { if self.len == 0 { return None; } self.len -= 1; let dir = self.coords[self.len]; let inv = self.inversion[self.len]; self.coords[self.len] = TreeDir::This; self.inversion[self.len] = false; Some((dir, inv)) } pub fn is_inverted(&self) -> bool { if self.len == 0 { false } else { self.inversion[self.len - 1] } } pub fn get_from<'a>(&self, mut tree: &'a TreeElement) -> Option<&'a TreeElement> { for i in 0..self.len { match &self.coords[i] { TreeDir::Left => { if let Some(t) = tree.left() { tree = t } else { return None; } } TreeDir::Right => { if let Some(t) = tree.right() { tree = t } else { return None; } } TreeDir::This => return Some(tree), } } Some(tree) } pub fn get_from_mut<'a>(&self, mut tree: &'a mut TreeElement) -> Option<&'a mut TreeElement> { for i in 0..self.len { match &self.coords[i] { TreeDir::Left => { if let Some(t) = tree.left_mut() { tree = t } else { return None; } } TreeDir::Right => { if let Some(t) = tree.right_mut() { tree = t } else { return None; } } TreeDir::This => return Some(tree), } } Some(tree) } }