use std::mem;
use crate::measure::Measured;
use crate::monoid::Monoid;
use crate::reference::{Ref, Refs};
pub enum NodeInner<R, V>
where
R: Refs<V>,
V: Measured,
{
#[doc(hidden)]
Leaf(V),
#[doc(hidden)]
Node2 {
measure: V::Measure,
left: Node<R, V>,
right: Node<R, V>,
},
#[doc(hidden)]
Node3 {
measure: V::Measure,
left: Node<R, V>,
middle: Node<R, V>,
right: Node<R, V>,
},
}
pub struct Node<R, V>
where
R: Refs<V>,
V: Measured,
{
inner: R::Node,
}
impl<R, V> Node<R, V>
where
R: Refs<V>,
V: Measured,
{
pub(crate) fn leaf(value: V) -> Self {
Node {
inner: R::Node::new(NodeInner::Leaf(value)),
}
}
pub(crate) fn node2(left: Self, right: Self) -> Self {
let measure = left.measure().join(&right.measure());
Node {
inner: R::Node::new(NodeInner::Node2 {
measure,
left,
right,
}),
}
}
pub(crate) fn node3(left: Self, middle: Self, right: Self) -> Self {
let measure = left
.measure()
.join(&middle.measure())
.join(&right.measure());
Node {
inner: R::Node::new(NodeInner::Node3 {
measure,
left,
middle,
right,
}),
}
}
pub(crate) fn lift<I>(iter: I) -> LiftNodesIter<I::IntoIter, R, V>
where
I: IntoIterator<Item = Node<R, V>>,
{
LiftNodesIter::new(iter.into_iter())
}
}
impl<R, V> Clone for Node<R, V>
where
R: Refs<V>,
V: Measured,
{
fn clone(&self) -> Self {
Node {
inner: self.inner.clone(),
}
}
}
impl<R, V> Measured for Node<R, V>
where
R: Refs<V>,
V: Measured,
{
type Measure = V::Measure;
fn measure(&self) -> Self::Measure {
match self.as_ref() {
NodeInner::Leaf(value) => value.measure(),
NodeInner::Node2 { measure, .. } => measure.clone(),
NodeInner::Node3 { measure, .. } => measure.clone(),
}
}
}
impl<R, V> AsRef<NodeInner<R, V>> for Node<R, V>
where
R: Refs<V>,
V: Measured,
{
fn as_ref(&self) -> &NodeInner<R, V> {
&*self.inner
}
}
pub(crate) struct LiftNodesIter<I, R, V>
where
I: Iterator<Item = Node<R, V>>,
R: Refs<V>,
V: Measured,
{
buff: [Option<Node<R, V>>; 5],
index: u8,
left: u8,
iter: I,
}
impl<I, R, V> LiftNodesIter<I, R, V>
where
I: Iterator<Item = Node<R, V>>,
R: Refs<V>,
V: Measured,
{
fn new(mut iter: I) -> Self {
let buff = [
iter.next(),
iter.next(),
iter.next(),
iter.next(),
iter.next(),
];
let left = buff.iter().map(|n| if n.is_some() { 1 } else { 0 }).sum();
LiftNodesIter {
buff,
index: 0,
left,
iter,
}
}
fn buff_next(&mut self) -> Node<R, V> {
let next = self.iter.next();
if next.is_none() {
self.left -= 1;
}
let node = mem::replace(&mut self.buff[self.index as usize], next).unwrap();
self.index = (self.index + 1) % 5;
node
}
}
impl<I, R, V> Iterator for LiftNodesIter<I, R, V>
where
I: Iterator<Item = Node<R, V>>,
R: Refs<V>,
V: Measured,
{
type Item = Node<R, V>;
fn next(&mut self) -> Option<Self::Item> {
match self.left {
0 => None,
2 | 4 => Some(Node::node2(self.buff_next(), self.buff_next())),
_ => Some(Node::node3(
self.buff_next(),
self.buff_next(),
self.buff_next(),
)),
}
}
}