fingertrees 0.2.11

Immutable persisten finger trees
Documentation
use std::ops::Add;

use crate::measure::Measured;
use crate::monoid::Monoid;
use crate::node::{Node, NodeInner};
use crate::reference::Refs;

#[derive(Clone)]
pub enum Digit<V> {
    One([V; 1]),
    Two([V; 2]),
    Three([V; 3]),
    Four([V; 4]),
}

impl<V> Digit<V>
where
    V: Measured,
{
    pub(crate) fn split<F>(&self, mut measure: V::Measure, pred: &mut F) -> (&[V], &V, &[V])
    where
        F: FnMut(&V::Measure) -> bool,
    {
        let slice = self.as_ref();
        if slice.len() == 1 {
            (&[], &slice[0], &[])
        } else {
            let slice = self.as_ref();
            for (index, item) in slice.iter().enumerate() {
                measure = measure.join(&item.measure());
                if pred(&measure) {
                    return (&slice[..index], &slice[index], &slice[index + 1..]);
                }
            }
            let index = slice.len() - 1;
            (&slice[..index], &slice[index], &[])
        }
    }

    pub(crate) fn find<F>(&self, mut measure: V::Measure, pred: &mut F) -> (V::Measure, &V)
    where
        F: FnMut(&V::Measure) -> bool,
    {
        let last = self.as_ref().len() - 1;
        for (index, value) in self.as_ref().iter().enumerate() {
            let next_measure = measure.join(&value.measure());
            if pred(&next_measure) || index == last {
                return (measure, value);
            }
            measure = next_measure;
        }
        unreachable!()
    }
}

impl<'a, V, R> Add<R> for &'a Digit<V>
where
    V: Clone,
    R: AsRef<[V]>,
{
    type Output = Digit<V>;

    fn add(self, other: R) -> Self::Output {
        match (self.as_ref(), other.as_ref()) {
            (_, []) => self.clone(),
            ([v0], [v1]) => Digit::Two([v0.clone(), v1.clone()]),
            ([v0], [v1, v2]) => Digit::Three([v0.clone(), v1.clone(), v2.clone()]),
            ([v0], [v1, v2, v3]) => Digit::Four([v0.clone(), v1.clone(), v2.clone(), v3.clone()]),
            ([v0, v1], [v2]) => Digit::Three([v0.clone(), v1.clone(), v2.clone()]),
            ([v0, v1], [v2, v3]) => Digit::Four([v0.clone(), v1.clone(), v2.clone(), v3.clone()]),
            ([v0, v1, v2], [v3]) => Digit::Four([v0.clone(), v1.clone(), v2.clone(), v3.clone()]),
            _ => panic!(
                "impossible to create digit of size: {}",
                self.as_ref().len() + other.as_ref().len(),
            ),
        }
    }
}

impl<V: Measured> Measured for Digit<V> {
    type Measure = V::Measure;

    fn measure(&self) -> Self::Measure {
        self.as_ref()
            .iter()
            .fold(Self::Measure::unit(), |measure, val| {
                measure.join(&val.measure())
            })
    }
}

impl<V> AsRef<[V]> for Digit<V> {
    fn as_ref(&self) -> &[V] {
        match self {
            Digit::One(v) => v,
            Digit::Two(v) => v,
            Digit::Three(v) => v,
            Digit::Four(v) => v,
        }
    }
}

impl<'a, V> From<&'a [V]> for Digit<V>
where
    V: Clone,
{
    fn from(slice: &'a [V]) -> Digit<V> {
        match slice {
            [v0] => Digit::One([v0.clone()]),
            [v0, v1] => Digit::Two([v0.clone(), v1.clone()]),
            [v0, v1, v2] => Digit::Three([v0.clone(), v1.clone(), v2.clone()]),
            [v0, v1, v2, v3] => Digit::Four([v0.clone(), v1.clone(), v2.clone(), v3.clone()]),
            _ => panic!("immposible to create digit from of size: {}", slice.len()),
        }
    }
}

impl<'a, R, V: Measured> From<&'a Node<R, V>> for Digit<Node<R, V>>
where
    R: Refs<V>,
    V: Measured,
{
    fn from(node: &'a Node<R, V>) -> Digit<Node<R, V>> {
        match node.as_ref() {
            NodeInner::Leaf(..) => Digit::One([node.clone()]),
            NodeInner::Node2 { left, right, .. } => Digit::Two([left.clone(), right.clone()]),
            NodeInner::Node3 {
                left,
                middle,
                right,
                ..
            } => Digit::Three([left.clone(), middle.clone(), right.clone()]),
        }
    }
}