odsek 0.1.0

Lazy, pull-based composition of mathematical interval sets with open/closed endpoints, no_std-compatible.
Documentation
use crate::{EndpointToggle, Interval, Intervals, LeftT};

/// Adapter trait providing the `.map(fun)` builder method on any [`Intervals`].
///
/// Blanket-implemented for every `Intervals` whose endpoint is `Clone +
/// EndpointToggle`, so calling `.map(...)` on a stream just works.
pub trait InIntervalsMap: Sized {
    /// The endpoint type of the underlying stream.
    type Endpoint;
    /// Transform each interval's value with `fun`, leaving endpoints unchanged.
    fn map<F>(self, fun: F) -> IntervalsMap<Self, F>;
}

impl<I> InIntervalsMap for I
where
    I: Intervals + Sized,
    I::Endpoint: Clone + EndpointToggle,
{
    type Endpoint = <I as Intervals>::Endpoint;
    fn map<F>(self, fun: F) -> IntervalsMap<Self, F>
    where
        Self: Sized,
    {
        IntervalsMap { it: self, fun }
    }
}

/// An [`Intervals`] stream whose values are produced by applying a function
/// to the values of an inner stream.
///
/// Construct via [`InIntervalsMap::map`].
pub struct IntervalsMap<It, F> {
    it: It,
    fun: F,
}

impl<It, F, Out> Intervals for IntervalsMap<It, F>
where
    It: Intervals,
    It::Endpoint: Clone,
    F: Fn(&It::Value) -> Out,
    It::Value: Copy,
{
    type Endpoint = It::Endpoint;
    type Value = Out;

    fn head(
        &mut self,
        pos: Option<LeftT<Self::Endpoint>>,
    ) -> Option<Interval<Self::Endpoint, Out>> {
        let v = self.it.head(pos);
        match v {
            Some(i) => Some(Interval::new_lr(
                i.left(),
                i.right(),
                (self.fun)(&i.value()),
            )),
            None => None,
        }
    }
}