1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! Some simple helpers for recursive sampling.
use crate::{Random, Sample};
use std::ops::Range;

pub trait Recursion {
    type Output;

    fn recurse(&self, g: &mut Random, inner: RecursiveSampler<Self>) -> Self::Output
    where
        Self: Sized;
}

#[derive(Debug, Clone)]
pub struct RecursiveSampler<G> {
    pub depth: Option<Range<usize>>,
    pub node: G,
}

impl<G: Clone> RecursiveSampler<G> {
    fn lower(&self) -> Self {
        let depth = self
            .depth
            .as_ref()
            .map(|d| d.start.saturating_sub(1)..d.end.saturating_sub(1));
        Self {
            depth,
            ..self.clone()
        }
    }
}

impl<G, N> Sample for RecursiveSampler<G>
where
    G: Recursion<Output = N> + Sample<Output = N> + Clone,
    N: 'static,
{
    type Output = N;

    fn generate(&self, g: &mut Random) -> Self::Output {
        match &self.depth {
            Some(depth) => {
                if depth.start > 0 {
                    self.node.recurse(g, self.lower())
                } else {
                    if depth.end > 0 {
                        self.node.recurse(g, self.lower())
                    } else {
                        self.node.generate(g)
                    }
                }
            }
            None => self.node.recurse(g, self.lower()),
        }
    }
}