use crate::index::{IndexType, NodeIndex};
use crate::interval::Interval;
#[cfg(feature = "graphviz")]
use std::fmt::Display;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub struct Node<T, V, Ix> {
pub left: Option<NodeIndex<Ix>>,
pub right: Option<NodeIndex<Ix>>,
pub parent: Option<NodeIndex<Ix>>,
pub color: Color,
pub interval: Option<Interval<T>>,
pub max_index: Option<NodeIndex<Ix>>,
pub value: Option<V>,
}
impl<T, V, Ix> Node<T, V, Ix>
where
T: Ord,
{
pub fn interval(&self) -> &Interval<T> {
self.interval.as_ref().unwrap()
}
pub fn value(&self) -> &V {
self.value.as_ref().unwrap()
}
pub fn value_mut(&mut self) -> &mut V {
self.value.as_mut().unwrap()
}
pub fn take_value(&mut self) -> V {
self.value.take().unwrap()
}
pub fn set_value(value: V) -> impl FnOnce(&mut Node<T, V, Ix>) -> V {
move |node: &mut Node<T, V, Ix>| node.value.replace(value).unwrap()
}
}
impl<T, V, Ix> Node<T, V, Ix>
where
T: Ord,
Ix: IndexType,
{
pub(crate) fn max_index(&self) -> NodeIndex<Ix> {
self.max_index.unwrap()
}
pub(crate) fn set_max_index(max_index: NodeIndex<Ix>) -> impl FnOnce(&mut Node<T, V, Ix>) {
move |node: &mut Node<T, V, Ix>| {
let _ignore = node.max_index.replace(max_index);
}
}
pub(crate) fn left(&self) -> NodeIndex<Ix> {
self.left.unwrap()
}
pub(crate) fn set_left(left: NodeIndex<Ix>) -> impl FnOnce(&mut Node<T, V, Ix>) {
move |node: &mut Node<T, V, Ix>| {
let _ignore = node.left.replace(left);
}
}
pub(crate) fn right(&self) -> NodeIndex<Ix> {
self.right.unwrap()
}
pub(crate) fn set_right(right: NodeIndex<Ix>) -> impl FnOnce(&mut Node<T, V, Ix>) {
move |node: &mut Node<T, V, Ix>| {
let _ignore = node.right.replace(right);
}
}
pub(crate) fn parent(&self) -> NodeIndex<Ix> {
self.parent.unwrap()
}
pub(crate) fn set_parent(parent: NodeIndex<Ix>) -> impl FnOnce(&mut Node<T, V, Ix>) {
move |node: &mut Node<T, V, Ix>| {
let _ignore = node.parent.replace(parent);
}
}
pub(crate) fn is_sentinel(&self) -> bool {
self.interval.is_none()
}
pub(crate) fn sentinel(&self) -> Option<&Self> {
self.interval.is_some().then_some(self)
}
pub(crate) fn color(&self) -> Color {
self.color
}
pub(crate) fn is_black(&self) -> bool {
matches!(self.color, Color::Black)
}
pub(crate) fn is_red(&self) -> bool {
matches!(self.color, Color::Red)
}
pub(crate) fn set_color(color: Color) -> impl FnOnce(&mut Node<T, V, Ix>) {
move |node: &mut Node<T, V, Ix>| {
node.color = color;
}
}
}
#[cfg(feature = "graphviz")]
impl<T, V, Ix> Node<T, V, Ix>
where
T: Ord + Display,
V: Display,
Ix: IndexType,
{
pub(crate) fn draw<W: std::io::Write>(
&self,
index: usize,
mut writer: W,
) -> std::io::Result<()> {
writeln!(
writer,
" {} [label=\"i={}\\n{}: {}\\n\", fillcolor={}, style=filled]",
index,
index,
self.interval.as_ref().unwrap(),
self.value.as_ref().unwrap(),
if self.is_red() { "salmon" } else { "grey65" }
)?;
if !self.left.unwrap().is_sentinel() {
writeln!(
writer,
" {} -> {} [label=\"L\"]",
index,
self.left.unwrap().index()
)?;
}
if !self.right.unwrap().is_sentinel() {
writeln!(
writer,
" {} -> {} [label=\"R\"]",
index,
self.right.unwrap().index()
)?;
}
Ok(())
}
}
#[cfg(feature = "graphviz")]
impl<T, V, Ix> Node<T, V, Ix>
where
T: Display + Ord,
Ix: IndexType,
{
pub(crate) fn draw_without_value<W: std::io::Write>(
&self,
index: usize,
mut writer: W,
) -> std::io::Result<()> {
writeln!(
writer,
" {} [label=\"i={}: {}\", fillcolor={}, style=filled]",
index,
index,
self.interval.as_ref().unwrap(),
if self.is_red() { "salmon" } else { "grey65" }
)?;
if !self.left.unwrap().is_sentinel() {
writeln!(
writer,
" {} -> {} [label=\"L\"]",
index,
self.left.unwrap().index()
)?;
}
if !self.right.unwrap().is_sentinel() {
writeln!(
writer,
" {} -> {} [label=\"R\"]",
index,
self.right.unwrap().index()
)?;
}
Ok(())
}
}
impl<T, V, Ix> Node<T, V, Ix>
where
T: Ord,
Ix: IndexType,
{
pub fn new(interval: Interval<T>, value: V, index: NodeIndex<Ix>) -> Self {
Node {
interval: Some(interval),
value: Some(value),
max_index: Some(index),
left: Some(NodeIndex::SENTINEL),
right: Some(NodeIndex::SENTINEL),
parent: Some(NodeIndex::SENTINEL),
color: Color::Red,
}
}
pub fn new_sentinel() -> Self {
Node {
interval: None,
value: None,
max_index: None,
left: None,
right: None,
parent: None,
color: Color::Black,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Color {
Red,
Black,
}
#[cfg(feature = "serde")]
#[cfg(test)]
mod tests {
use super::*;
use serde_json::{json, Value};
#[test]
fn test_node_serialize_deserialize() {
let node = Node::<i32, i32, u8> {
left: Some(NodeIndex::new(0)),
right: Some(NodeIndex::new(1)),
parent: Some(NodeIndex::new(2)),
color: Color::Red,
interval: Some(Interval::new(10, 20)),
max_index: Some(NodeIndex::new(3)),
value: Some(42),
};
let serialized = serde_json::to_string(&node).unwrap();
let expected = json!({
"left": 0,
"right": 1,
"parent": 2,
"color": "Red",
"interval": [10,20],
"max_index": 3,
"value": 42
});
let actual: Value = serde_json::from_str(&serialized).unwrap();
assert_eq!(expected, actual);
let deserialized: Node<i32, i32, u8> = serde_json::from_str(&serialized).unwrap();
assert_eq!(node.left, deserialized.left);
assert_eq!(node.right, deserialized.right);
assert_eq!(node.parent, deserialized.parent);
assert_eq!(node.color, deserialized.color);
assert_eq!(node.interval, deserialized.interval);
assert_eq!(node.max_index, deserialized.max_index);
assert_eq!(node.value, deserialized.value);
}
}