1use crate::{Random, Sample};
3use std::ops::Range;
4
5pub trait Recursion {
6 type Output;
7
8 fn recurse(&self, g: &mut Random, inner: RecursiveSampler<Self>) -> Self::Output
9 where
10 Self: Sized;
11}
12
13#[derive(Debug, Clone)]
14pub struct RecursiveSampler<G> {
15 pub depth: Option<Range<usize>>,
16 pub node: G,
17}
18
19impl<G: Clone> RecursiveSampler<G> {
20 fn lower(&self) -> Self {
21 let depth = self
22 .depth
23 .as_ref()
24 .map(|d| d.start.saturating_sub(1)..d.end.saturating_sub(1));
25 Self {
26 depth,
27 ..self.clone()
28 }
29 }
30}
31
32impl<G, N> Sample for RecursiveSampler<G>
33where
34 G: Recursion<Output = N> + Sample<Output = N> + Clone,
35 N: 'static,
36{
37 type Output = N;
38
39 fn generate(&mut self, g: &mut Random) -> Self::Output {
40 match &self.depth {
41 Some(depth) => {
42 if depth.start > 0 {
43 self.node.recurse(g, self.lower())
44 } else {
45 if depth.end > 0 {
46 self.node.recurse(g, self.lower())
47 } else {
48 self.node.generate(g)
49 }
50 }
51 }
52 None => self.node.recurse(g, self.lower()),
53 }
54 }
55}