boulder 0.3.0

Like a builder, but heavier.
Documentation
//! Standard generator implementations.

use crate::Generator;

pub use boulder_derive::repeat as Repeat;
pub use boulder_derive::string_pattern as Pattern;

use num::One;

/// The same value every time.
///
/// In general, using a lambda has fewer restrictions than using
/// [`Const`], because you can avoid the [`Clone`] requirement on
/// your type.
///
/// Example:
/// ```rust
/// use boulder::{Const, Generator};
///
/// let mut g = Const(1);
/// assert_eq!(g.generate(), 1);
/// assert_eq!(g.generate(), 1);
/// assert_eq!(g.generate(), 1);
/// ```
#[derive(Clone)]
pub struct Const<T>(pub T);

impl<T> Const<T> {
    pub fn new(value: T) -> Self {
        Self(value)
    }
}

impl<T: Clone + 'static> Generator for Const<T> {
    type Output = T;
    fn generate(&mut self) -> Self::Output {
        self.0.clone()
    }
}

/// An increasing sequence.
///
/// The type `T` must implement [`AddAssign`](std::ops::AddAssign) +
/// [`num::One`] + [`Clone`], which is true for all primitive numeric
/// types. The output value increases by 1 on each call.
///
/// Example:
/// ```rust
/// use boulder::{Generator, Inc};
///
/// let mut g = Inc(5);
/// assert_eq!(g.generate(), 5);
/// assert_eq!(g.generate(), 6);
/// assert_eq!(g.generate(), 7);
/// ```
#[derive(Clone)]
pub struct Inc<T>(pub T);

impl<T> Generator for Inc<T>
where
    T: core::ops::AddAssign<T> + One + Clone + 'static,
{
    type Output = T;
    fn generate(&mut self) -> T {
        let res = self.0.clone();
        self.0 += T::one();
        res
    }
}

/// Recycle values from an iterator.
///
/// Since generators must produce an infinite sequence, this cycles
/// the iterator to prevent it being exhausted.
///
/// Example:
/// ```rust
/// use boulder::{Cycle, Generator};
///
/// let mut g = Cycle::new((1..3_i32).into_iter());
/// assert_eq!(g.generate(), 1);
/// assert_eq!(g.generate(), 2);
/// assert_eq!(g.generate(), 1);
/// ```
pub struct Cycle<T>(pub(crate) ::std::iter::Cycle<T>);

impl<T: Iterator + Clone> Cycle<T> {
    pub fn new(iter: T) -> Self {
        Self(iter.cycle())
    }
}

impl<S, T> Generator for Cycle<S>
where
    S: Iterator<Item = T> + Clone + 'static,
{
    type Output = T;
    fn generate(&mut self) -> T {
        self.0.next().unwrap()
    }
}

/// Wrap sequence of `T` in [`Option<T>`].
///
/// This converts a generator of `T` into a stream of [`Option<T>`] by
/// wrapping each value in `Some`.
///
/// Example:
/// ```rust
/// use boulder::{Generator, Inc, Some as GSome};
///
/// let mut g = GSome(Inc(2));
/// assert_eq!(g.generate(), Some(2));
/// assert_eq!(g.generate(), Some(3));
/// assert_eq!(g.generate(), Some(4));
/// ```
pub struct Some<T>(pub T);

impl<T: Generator> Generator for Some<T> {
    type Output = Option<<T as Generator>::Output>;
    fn generate(&mut self) -> Self::Output {
        ::std::option::Option::Some(self.0.generate())
    }
}

impl<F, T> Generator for F
where
    F: FnMut() -> T + 'static,
{
    type Output = T;
    fn generate(&mut self) -> Self::Output {
        self()
    }
}

/// Collections from an underlying sequence.
///
/// Produce collections from a pair of generators, one for the values
/// themselves, one for the size of yielded collection.
///
/// Example:
/// ```rust
/// use boulder::{Cycle, Generator, Repeat, Sample};
///
/// let mut g = Sample::<_, _, Vec<_>>::new(Cycle::new((1..5).into_iter()), Repeat::new(1usize..3usize));
/// assert_eq!(g.generate(), vec![1]);
/// assert_eq!(g.generate(), vec![2, 3]);
/// assert_eq!(g.generate(), vec![4]);
/// ```
pub struct Sample<T, U, V> {
    pub(crate) value: T,
    pub(crate) count: U,
    pub(crate) _result_marker: core::marker::PhantomData<V>,
}

impl<T, U, V> Sample<T, U, V>
where
    T: Generator,
    U: Generator<Output = usize>,
    V: FromIterator<<T as Generator>::Output> + 'static,
{
    /// Create a new generator.
    ///
    /// The values it yields (of type `V`) will contain a number of
    /// elements of type type `T` which are determined by the sequence
    /// produced by `count`. The actual elements are generated by
    /// `value`.
    ///
    /// Example:
    /// ```rust
    /// use boulder::{Generator, Inc, Pattern, Sample};
    ///
    /// let mut g = Sample::new(
    ///     Pattern!("hello-{}", Inc(2i32)),
    ///     Inc(1usize)
    /// );
    /// let s1: Vec<_> = g.generate();
    /// assert_eq!(s1.len(), 1);
    /// assert_eq!(s1[0], "hello-2".to_string());
    /// let s2 = g.generate();
    /// assert_eq!(s2.len(), 2);
    /// assert_eq!(s2[0], "hello-3".to_string());
    /// assert_eq!(s2[1], "hello-4".to_string());
    /// ```
    pub fn new(value: T, count: U) -> Self {
        Self {
            value,
            count,
            _result_marker: Default::default(),
        }
    }
}

impl<T, U, V, X> Generator for Sample<T, U, V>
where
    T: Generator<Output = X>,
    U: Generator<Output = usize>,
    V: FromIterator<X> + 'static,
{
    type Output = V;
    fn generate(&mut self) -> Self::Output {
        super::GeneratorMutIterator {
            gen: &mut self.value,
        }
        .take(self.count.generate())
        .collect()
    }
}

/// Increasing timestamps.
///
/// Each output is a [`DateTime`](chrono::DateTime), which is
/// separated from the previous value by a fixed
/// [`Duration`](chrono::Duration).
///
/// Example:
/// ```rust
/// use boulder::{Generator, Time};
/// use chrono::{DateTime, Duration};
///
/// let mut g = Time::new(DateTime::parse_from_rfc2822("Wed, 18 May 2022 15:16:00 GMT").unwrap(), Duration::days(1));
/// assert_eq!(g.generate(), DateTime::parse_from_rfc2822("Wed, 18 May 2022 15:16:00 GMT").unwrap());
/// assert_eq!(g.generate(), DateTime::parse_from_rfc2822("Thu, 19 May 2022 15:16:00 GMT").unwrap());
/// assert_eq!(g.generate(), DateTime::parse_from_rfc2822("Fri, 20 May 2022 15:16:00 GMT").unwrap());
/// ```
pub struct Time<T: chrono::TimeZone> {
    pub(crate) instant: chrono::DateTime<T>,
    pub(crate) step: chrono::Duration,
}

impl<T: chrono::TimeZone> Time<T> {
    /// Create a new [`Time`] generator.
    ///
    /// Here
    ///
    /// - `start` is the first [`DateTime`](chrono::DateTime) in the
    ///   sequence.
    ///
    /// - `step` is the [`Duration`](chrono::Duration) separating any
    ///   two adjacent times in the sequence.
    ///
    /// Example:
    /// ```rust
    /// use boulder::{Generator, Time};
    /// use chrono::{DateTime, Duration};
    ///
    /// let mut g = Time::new(
    ///     DateTime::parse_from_rfc3339("2022-03-31T17:40:00+01:00").unwrap(),
    ///     Duration::hours(1)
    /// );
    /// let t = g.generate();
    /// assert_eq!(t, DateTime::parse_from_rfc3339("2022-03-31T17:40:00+01:00").unwrap());
    /// let t = g.generate();
    /// assert_eq!(t, DateTime::parse_from_rfc3339("2022-03-31T18:40:00+01:00").unwrap());
    /// let t = g.generate();
    /// assert_eq!(t, DateTime::parse_from_rfc3339("2022-03-31T19:40:00+01:00").unwrap());
    /// ```
    pub fn new(start: chrono::DateTime<T>, step: chrono::Duration) -> Self {
        Self {
            instant: start,
            step,
        }
    }
}

impl<T: chrono::TimeZone + 'static> Generator for Time<T> {
    type Output = chrono::DateTime<T>;
    fn generate(&mut self) -> Self::Output {
        let res = self.instant.clone();
        self.instant = self.instant.clone() + self.step;
        res
    }
}

/// Subsets of a base collection.
///
/// The pattern for the yielded values is:
/// 1. `vec![]`
/// 2. `vec![a]`
/// 3. `vec![b]`
/// 4. `vec![a,b]`
/// 5. `vec![c]`
/// 6. `vec![a,c]`
/// 7. `vec![b,c]`
/// 8. `vec![a,b,c]`
/// 9. ...
///
/// where the `a` is the first element of the base collection, `b` is
/// the second, and so on.
///
/// Example:
/// ```rust
/// use boulder::{Generator, Subsets};
///
/// let mut g = Subsets::new(1..4);
/// assert_eq!(g.generate(), vec![]);
/// assert_eq!(g.generate(), vec![1]);
/// assert_eq!(g.generate(), vec![2]);
/// assert_eq!(g.generate(), vec![1,2]);
/// ```
#[derive(Clone)]
pub struct Subsets<T: Clone> {
    pub(crate) base: Vec<T>,
    pub(crate) index: usize,
}

impl<T: Clone> Subsets<T> {
    /// Create a new generator.
    ///
    /// `base` will be collected into a [`Vec`] for re-sampling.
    pub fn new<X: IntoIterator<Item = T>>(base: X) -> Self {
        Self {
            base: base.into_iter().collect(),
            index: 0,
        }
    }
}

impl<T: Clone + 'static> Generator for Subsets<T> {
    type Output = Vec<T>;
    fn generate(&mut self) -> Self::Output {
        let mut v = Vec::new();
        for i in 0..std::cmp::min(std::mem::size_of::<usize>() * 8, self.base.len()) {
            if self.index & (1usize << i) != 0 {
                v.push(self.base[i].clone());
            }
        }
        self.index += 1;
        v
    }
}

/// Repeat a provided collection.
///
/// This is a less flexible, but more concisely constructed, version
/// of [`Cycle`] that starts from a container instead of an iterator.
///
/// Example:
/// ```rust
/// use boulder::{Generator, Repeat};
///
/// let mut g = Repeat::new(1..3);
/// assert_eq!(g.generate(), 1);
/// assert_eq!(g.generate(), 2);
/// assert_eq!(g.generate(), 1);
/// ```
#[derive(Clone)]
pub struct Repeat<T: Clone> {
    pub(crate) base: Vec<T>,
    pub(crate) index: usize,
}

impl<T: Clone> Repeat<T> {
    pub fn new<X: IntoIterator<Item = T>>(base: X) -> Self {
        Self {
            base: base.into_iter().collect(),
            index: 0,
        }
    }
}

impl<T: Clone + 'static> Generator for Repeat<T> {
    type Output = T;
    fn generate(&mut self) -> Self::Output {
        let res = self.base[self.index % self.base.len()].clone();
        self.index = (self.index + 1usize) % self.base.len();
        res
    }
}