1
use crate::{Reduction, Rule};
2
use multipeek::multipeek;
3
use uniplate::Uniplate;
4

            
5
/// Returns the first result if the iterator has only one, otherwise calls `select`.
6
37
pub(crate) fn one_or_select<T, M, R>(
7
37
    select: impl Fn(&T, &mut dyn Iterator<Item = (&R, Reduction<T, M>)>) -> Option<Reduction<T, M>>,
8
37
    t: &T,
9
37
    rs: &mut dyn Iterator<Item = (&R, Reduction<T, M>)>,
10
37
) -> Option<Reduction<T, M>>
11
37
where
12
37
    T: Uniplate,
13
37
    R: Rule<T, M>,
14
37
{
15
37
    let mut rs = multipeek(rs);
16
37
    if rs.peek_nth(1).is_none() {
17
36
        return rs.next().map(|(_, r)| r);
18
1
    }
19
1
    select(t, &mut rs)
20
37
}
21

            
22
/// Returns the first available `Reduction` if there is one, otherwise returns `None`.
23
///
24
/// This is a good default selection strategy, especially when you expect only one possible result.
25
1
pub fn select_first<T, M, R>(
26
1
    _: &T,
27
1
    rs: &mut dyn Iterator<Item = (&R, Reduction<T, M>)>,
28
1
) -> Option<Reduction<T, M>>
29
1
where
30
1
    T: Uniplate,
31
1
    R: Rule<T, M>,
32
1
{
33
1
    rs.next().map(|(_, r)| r)
34
1
}
35

            
36
// TODO: Add more selection strategies:
37
// - random
38
// - smallest subtree
39
// - ask the user for input via blocking I/O
40
// - panic if there is more than 1 result, otherwise return the first