use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;
use std::iter::FromIterator;
use crate::reflection;
use crate::utils;
use crate::Predicate;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InPredicate<T>
where
T: PartialEq + fmt::Debug,
{
inner: utils::DebugAdapter<Vec<T>>,
}
impl<T> InPredicate<T>
where
T: Ord + fmt::Debug,
{
pub fn sort(self) -> OrdInPredicate<T> {
let mut items = self.inner.debug;
items.sort();
OrdInPredicate {
inner: utils::DebugAdapter::new(items),
}
}
}
impl<P, T> Predicate<P> for InPredicate<T>
where
T: std::borrow::Borrow<P> + PartialEq + fmt::Debug,
P: PartialEq + fmt::Debug + ?Sized,
{
fn eval(&self, variable: &P) -> bool {
self.inner.debug.iter().any(|x| x.borrow() == variable)
}
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
utils::default_find_case(self, expected, variable).map(|case| {
case.add_product(reflection::Product::new(
"var",
utils::DebugAdapter::new(variable).to_string(),
))
})
}
}
impl<T> reflection::PredicateReflection for InPredicate<T>
where
T: PartialEq + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}
impl<T> fmt::Display for InPredicate<T>
where
T: PartialEq + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::new(f.alternate());
write!(
f,
"{} {} {}",
palette.var("var"),
palette.description("in"),
palette.expected("values")
)
}
}
pub fn in_iter<I, T>(iter: I) -> InPredicate<T>
where
T: PartialEq + fmt::Debug,
I: IntoIterator<Item = T>,
{
InPredicate {
inner: utils::DebugAdapter::new(Vec::from_iter(iter)),
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OrdInPredicate<T>
where
T: Ord + fmt::Debug,
{
inner: utils::DebugAdapter<Vec<T>>,
}
impl<P, T> Predicate<P> for OrdInPredicate<T>
where
T: std::borrow::Borrow<P> + Ord + fmt::Debug,
P: Ord + fmt::Debug + ?Sized,
{
fn eval(&self, variable: &P) -> bool {
self.inner
.debug
.binary_search_by(|x| x.borrow().cmp(variable))
.is_ok()
}
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
utils::default_find_case(self, expected, variable).map(|case| {
case.add_product(reflection::Product::new(
"var",
utils::DebugAdapter::new(variable).to_string(),
))
})
}
}
impl<T> reflection::PredicateReflection for OrdInPredicate<T>
where
T: Ord + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}
impl<T> fmt::Display for OrdInPredicate<T>
where
T: Ord + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::new(f.alternate());
write!(
f,
"{} {} {}",
palette.var("var"),
palette.description("in"),
palette.expected("values")
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
inner: utils::DebugAdapter<HashSet<T>>,
}
impl<P, T> Predicate<P> for HashableInPredicate<T>
where
T: std::borrow::Borrow<P> + Hash + Eq + fmt::Debug,
P: Hash + Eq + fmt::Debug + ?Sized,
{
fn eval(&self, variable: &P) -> bool {
self.inner.debug.contains(variable)
}
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
utils::default_find_case(self, expected, variable).map(|case| {
case.add_product(reflection::Product::new(
"var",
utils::DebugAdapter::new(variable).to_string(),
))
})
}
}
impl<T> reflection::PredicateReflection for HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}
impl<T> fmt::Display for HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let palette = crate::Palette::new(f.alternate());
write!(
f,
"{} {} {}",
palette.var("var"),
palette.description("in"),
palette.expected("values")
)
}
}
pub fn in_hash<I, T>(iter: I) -> HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
I: IntoIterator<Item = T>,
{
HashableInPredicate {
inner: utils::DebugAdapter::new(HashSet::from_iter(iter)),
}
}