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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
use std::fmt::Debug;
use itertools::Itertools;
use super::State;
use crate::{
core::{LVar, VarId},
resolve_any, AnyVal,
};
/**
An opaque list of untyped [`LVar`]s.
This is usually used to set up a watch on behalf of a [`Constraint`](crate::constraints::Constraint).
Consider generating this with the [`resolve_1`](crate::constraints::resolve_1), [`resolve_2`](crate::constraints::resolve_2), [`OneOfTwo`](crate::constraints::OneOfTwo)
or [`TwoOfThree`](crate::constraints::TwoOfThree) helpers.
It is also the return value of [`State::vars()`].
*/
#[derive(Debug)]
pub struct LVarList(pub(crate) Vec<VarId>);
impl LVarList {
/// Create an `LVarList` from a single [`LVar`].
pub fn one<A>(a: &LVar<A>) -> Self {
LVarList(vec![a.id])
}
/// Create an `LVarList` from two [`LVar`]s.
pub fn two<A, B>(a: &LVar<A>, b: &LVar<B>) -> Self {
LVarList(vec![a.id, b.id])
}
/// Generate a new `LVarList` based on `&self` with any variables that have
/// been been resolved in the passed in state removed.
#[must_use]
pub fn without_resolved_in(&self, state: &State) -> LVarList {
LVarList(
self.0
.iter()
.filter_map(|id| {
if resolve_any(&state.values, &AnyVal::Var(*id)).is_resolved() {
None
} else {
Some(*id)
}
})
.collect(),
)
}
/// Returns the number of [`LVar`]s.
pub fn len(&self) -> usize {
self.0.len()
}
/// Returns true if the `LVarList` contains no elements.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Produce a single deduplicated `LVarList` from an [`Iterator`] of `LVarList`s.
pub fn flatten(lists: impl Iterator<Item = LVarList>) -> LVarList {
LVarList(lists.flat_map(|list| list.0.into_iter()).unique().collect())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_lvarlist_len() {
assert_eq!(LVarList(vec![]).len(), 0);
assert_eq!(LVarList(vec![1]).len(), 1);
}
}