diceprop/
vars.rs

1use dicetest::hint;
2use std::fmt::Debug;
3use std::fmt::Write;
4
5use crate::{Elem, Eval};
6
7/// Represents elements that were chosen from a set and that can be used as variables in properties.
8///
9/// It contains `N` elements of type `S`.
10#[derive(Clone, Copy)]
11pub struct Vars<'a, S: Debug, const N: usize> {
12    /// The name of the set the elements were chosen from.
13    pub set: &'a str,
14    /// The elements of the set.
15    pub elems: [Elem<'a, S>; N],
16}
17
18impl<'a, S: Debug, const N: usize> Vars<'a, S, N> {
19    pub fn new(set: &'a str, elems: [Elem<'a, S>; N]) -> Self {
20        Self { set, elems }
21    }
22
23    /// Returns [`Eval`]s that contain the variables.
24    ///
25    /// This operation will log the variables via [`dicetest::hints`].
26    pub fn eval(self) -> [Eval<&'a str, S>; N] {
27        let set = self.set;
28        let elems = self.elems;
29
30        fn elem_names<S: Debug, const N: usize>(elems: &[Elem<S>; N]) -> String {
31            let mut acc = String::new();
32            for (i, elem) in elems.iter().enumerate() {
33                if i == 0 {
34                    write!(acc, "{}", elem.name).unwrap();
35                } else {
36                    write!(acc, ", {}", elem.name).unwrap();
37                }
38            }
39            acc
40        }
41
42        hint!("{} of {}", elem_names(&elems), set);
43        elems.map(|elem| elem.eval())
44    }
45
46    /// Returns a [`Vars`] with the same names and references to the original values.
47    pub fn as_ref<'b: 'a>(&'b self) -> Vars<'a, &'b S, N> {
48        let elems = array_init::array_init(|i| self.elems[i].as_ref());
49        Vars::new(self.set, elems)
50    }
51}