use num_derive::FromPrimitive;
#[derive(thiserror::Error,Debug)]
pub enum Error {
#[error("node is missing")]
NodeMissing,
#[error("node already exists")]
NodeExists,
#[error("out of range")]
OutOfRange,
#[error("there is no cursor")]
NoCursor,
#[error("tree connection is broken")]
BrokenConnection,
#[error("root node or broken connection")]
BrokenConnectionOrRoot,
#[error("non-root node or broken connection")]
BrokenConnectionOrNotRoot
}
#[derive(FromPrimitive,Clone,Copy)]
pub enum Side {
Left = 0,
Right = 1
}
#[derive(Clone)]
struct Node {
val: usize,
symbol: Option<usize>,
up: Option<usize>,
down: [Option<usize>;2]
}
pub struct Tree {
roots: Vec<Option<usize>>,
curs: Option<usize>,
pool: Vec<Node>
}
impl Tree {
pub fn create(len: usize,symbols: usize) -> Self {
let roots: Vec<Option<usize>> = vec![None;symbols];
let mut pool: Vec<Node> = Vec::new();
for i in 0..len {
pool.push(Node {val: i, symbol: None, up: None, down: [None,None]});
}
Self {
roots,
curs: None,
pool
}
}
fn chk_cursor(&self) -> Result<usize,Error> {
match self.curs {
None => Err(Error::NoCursor),
Some(curs) => {
match curs < self.pool.len() {
true => Ok(curs),
false => Err(Error::OutOfRange)
}
}
}
}
pub fn get_cursor(&self) -> Option<usize> {
self.curs
}
pub fn set_cursor(&mut self,curs: usize) -> Result<(),Error> {
match curs < self.pool.len() {
true => {
self.curs = Some(curs);
Ok(())
},
false => Err(Error::OutOfRange)
}
}
pub fn set_cursor_to_root(&mut self,symbol: usize) -> Result<(),Error> {
match self.roots[symbol] {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(())
}
}
}
pub fn up(&mut self) -> Result<usize,Error> {
match self.pool[self.chk_cursor()?].up {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(v)
}
}
}
pub fn down(&mut self,side: Side) -> Result<usize,Error> {
match self.pool[self.chk_cursor()?].down[side as usize] {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(v)
}
}
}
pub fn terminus(&mut self,side: Side) -> Result<usize,Error> {
let mut term = self.chk_cursor()?;
while let Ok(curs) = self.down(side) {
term = curs;
}
Ok(term)
}
pub fn get_down(&self) -> Result<[Option<usize>;2],Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].down)
}
pub fn get_parent_and_side(&mut self) -> Result<(usize,Side),Error> {
let curs = self.chk_cursor()?;
if let Some(parent) = self.pool[curs].up {
return match self.pool[parent].down {
[Some(v),_] if v==curs => Ok((parent,Side::Left)),
[_,Some(v)] if v==curs => Ok((parent,Side::Right)),
_ => Err(Error::BrokenConnection)
};
}
Err(Error::BrokenConnectionOrRoot)
}
pub fn get_symbol(&mut self) -> Result<usize,Error> {
let curs = self.chk_cursor()?;
if let Some(symbol) = self.pool[curs].symbol {
return match self.roots[symbol] {
Some(v) if v==curs => Ok(symbol),
_ => Err(Error::BrokenConnection)
};
}
Err(Error::BrokenConnectionOrNotRoot)
}
pub fn is_root(&self) -> Result<bool,Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].up==None)
}
pub fn is_leaf(&self) -> Result<bool,Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].down==[None,None])
}
pub fn is_free(&self,curs: usize) -> Result<bool,Error> {
match (self.pool[curs].symbol,self.pool[curs].up,self.pool[curs].down) {
(None,None,_) => Ok(true),
_ => Ok(false),
}
}
pub fn spawn(&mut self, val: usize, side: Side) -> Result<(),Error> {
if val >= self.pool.len() {
log::trace!("spawn out of range {}",val);
return Err(Error::OutOfRange);
}
let curs = self.chk_cursor()?;
if self.pool[curs].down[side as usize].is_some() {
log::trace!("spawn: cannot overwrite {}",self.pool[curs].down[side as usize].unwrap());
return Err(Error::NodeExists);
}
self.pool[curs].down[side as usize] = Some(val);
self.pool[val].up = Some(curs);
self.pool[val].down = [None,None];
Ok(())
}
pub fn spawn_root(&mut self, symbol: usize, curs: usize) -> Result<(),Error> {
if symbol >= self.roots.len() || curs >= self.pool.len() {
return Err(Error::OutOfRange);
}
if self.is_free(curs)? {
self.roots[symbol] = Some(curs);
self.pool[curs].symbol = Some(symbol);
self.pool[curs].up = None;
self.pool[curs].down = [None,None];
return Ok(())
}
log::trace!("spawn_root: cannot overwrite {}",curs);
Err(Error::NodeExists)
}
pub fn drop(&mut self) -> Result<(),Error> {
let curs = self.chk_cursor()?;
let maybe_parent = self.pool[curs].up;
let maybe_symbol = self.pool[curs].symbol;
if let Ok(_) = self.down(Side::Left) {
self.drop()?;
self.set_cursor(curs)?;
}
if let Ok(_) = self.down(Side::Right) {
self.drop()?;
self.set_cursor(curs)?;
}
if let Some(parent) = maybe_parent {
let (_,side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = None;
self.curs = Some(parent);
}
if let Some(symbol) = maybe_symbol {
self.roots[symbol] = None;
self.curs = None;
}
self.pool[curs].symbol = None;
self.pool[curs].up = None;
self.pool[curs].down = [None,None];
Ok(())
}
pub fn drop_branch(&mut self,side: Side) -> Result<(),Error> {
if let Ok(_) = self.down(side) {
self.drop()?;
}
Ok(())
}
pub fn cut_upward(&mut self) -> Result<(),Error> {
let (parent,side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = None;
self.pool[self.curs.unwrap()].up = None;
Ok(())
}
pub fn cut_downward(&mut self,side: Side) -> Result<(),Error> {
let curs: usize = self.chk_cursor()?;
if let Some(son) = self.pool[curs].down[side as usize] {
self.pool[curs].down[side as usize] = None;
self.pool[son].up = None;
}
Ok(())
}
pub fn move_node(&mut self,new_parent: usize,side: Side,force: bool) -> Result<(),Error> {
let curs: usize = self.chk_cursor()?;
match (self.pool[new_parent].down[side as usize],force) {
(None,_) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
},
(Some(_),true) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
self.set_cursor(new_parent)?;
self.drop_branch(side)?;
self.set_cursor(curs)?;
},
_ => {
log::trace!("move: cannot overwrite {}",self.pool[new_parent].down[side as usize].unwrap());
return Err(Error::NodeExists);
}
}
self.pool[new_parent].down[side as usize] = Some(curs);
self.pool[curs].up = Some(new_parent);
return Ok(());
}
pub fn move_node_to_root(&mut self,symbol: usize,force: bool) -> Result<(),Error> {
let curs: usize = self.chk_cursor()?;
match (self.roots[symbol],force) {
(None,_) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
},
(Some(old_root),true) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
self.set_cursor(old_root)?;
self.drop()?;
self.set_cursor(curs)?;
},
(Some(old_root),false) => {
log::trace!("move: cannot overwrite root {}",old_root);
return Err(Error::NodeExists);
}
}
self.roots[symbol] = Some(curs);
self.pool[curs].up = None;
self.pool[curs].symbol = Some(symbol);
return Ok(());
}
pub fn change_value(&mut self,new_val: usize,force: bool) -> Result<(),Error> {
let old_val = self.chk_cursor()?;
if new_val == old_val {
return Ok(());
}
match (self.is_free(new_val)?,force) {
(true,_) => {},
(false,false) => {
log::trace!("cannot change node value to {}",new_val);
return Err(Error::NodeExists)
},
(false,true) => {
self.set_cursor(new_val)?;
self.drop()?;
self.set_cursor(old_val)?;
}
}
if let Some(symbol) = self.pool[old_val].symbol {
self.roots[symbol] = Some(new_val);
}
if let Some(parent) = self.pool[old_val].up {
let (_,side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = Some(new_val);
}
if let Some(child) = self.pool[old_val].down[0] {
self.pool[child].up = Some(new_val);
}
if let Some(child) = self.pool[old_val].down[1] {
self.pool[child].up = Some(new_val);
}
self.pool[new_val] = self.pool[old_val].clone();
self.pool[new_val].val = new_val;
self.pool[old_val] = Node {
val: old_val,
symbol: None,
up: None,
down: [None,None]
};
self.curs = Some(new_val);
Ok(())
}
}