use std::{collections::HashMap, sync::LazyLock};
use super::Val;
pub(crate) type ContainPredType = fn(Val, Val) -> bool;
pub(crate) struct ContainPred;
impl ContainPred {
const LOGICAL_PRED_MAP: LazyLock<HashMap<&'static str, ContainPredType>> =
LazyLock::new(|| {
HashMap::from([
("-in", iin as _),
("-iin", iin as _),
("-cin", cin as _),
("-notin", inotin as _),
("-inotin", inotin as _),
("-cnotin", cnotin as _),
("-contains", icontains as _),
("-icontains", icontains as _),
("-ccontains", ccontains as _),
("-notcontains", inotcontains as _),
("-inotcontains", inotcontains as _),
("-cnotcontains", cnotcontains as _),
])
});
pub(crate) fn get(name: &str) -> Option<ContainPredType> {
Self::LOGICAL_PRED_MAP.get(name).copied()
}
}
fn contains_impl(a: Val, b: Val, case_insensitive: bool) -> bool {
let mut array = if let Val::Array(box_vec) = a {
box_vec
.iter()
.map(|v| v.cast_to_string())
.collect::<Vec<String>>()
} else {
vec![a.cast_to_string()]
};
let mut elem = b.cast_to_string();
if case_insensitive {
array = array
.iter()
.map(|s| s.to_ascii_lowercase())
.collect::<Vec<String>>();
elem = elem.to_ascii_lowercase();
}
array.contains(&elem)
}
pub fn iin(a: Val, b: Val) -> bool {
contains_impl(b, a, true)
}
pub fn cin(a: Val, b: Val) -> bool {
contains_impl(b, a, false)
}
pub fn inotin(a: Val, b: Val) -> bool {
!iin(a, b)
}
pub fn cnotin(a: Val, b: Val) -> bool {
!cin(a, b)
}
pub fn icontains(a: Val, b: Val) -> bool {
contains_impl(a, b, true)
}
pub fn ccontains(a: Val, b: Val) -> bool {
contains_impl(a, b, false)
}
pub fn inotcontains(a: Val, b: Val) -> bool {
!icontains(a, b)
}
pub fn cnotcontains(a: Val, b: Val) -> bool {
!ccontains(a, b)
}
#[cfg(test)]
mod tests {
use crate::PowerShellSession;
#[test]
fn test_in() {
let mut p = PowerShellSession::new();
assert_eq!(
p.safe_eval(r#" ($true, 1) -in ("True 1", 2) "#).unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" ($true, 1) -in (("True1", "1"), 2) "#)
.unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" 1 -in "3", "1" "#).unwrap(),
"True".to_string()
);
assert_eq!(p.safe_eval(r#" 1 -in "1" "#).unwrap(), "True".to_string());
assert_eq!(
p.safe_eval(r#" $true -iIn "true", "1" "#).unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" $true -cin "true", "1" "#).unwrap(),
"False".to_string()
);
}
#[test]
fn test_notin() {
let mut p = PowerShellSession::new();
assert_eq!(
p.safe_eval(r#" ($true, 1) -notin ("True 1", 2) "#)
.unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" ($true, 1) -inotin (("True1", "1"), 2) "#)
.unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" $true -notin "true", "1" "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" $true -inotin "true", "1" "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" $true -cnotin "true", "1" "#).unwrap(),
"True".to_string()
);
}
#[test]
fn test_constains() {
let mut p = PowerShellSession::new();
assert_eq!(
p.safe_eval(r#" ("True 1", 2) -Contains ($true, 1) "#)
.unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" (("True1", "1"), 2) -contains ($true, 1) "#)
.unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" "3", "1" -contains 1 "#).unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" "1" -contains 1 "#).unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" "true", "1" -icontains $true "#).unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" "true", "1" -ccontains $true "#).unwrap(),
"False".to_string()
);
}
#[test]
fn test_notconstains() {
let mut p = PowerShellSession::new();
assert_eq!(
p.safe_eval(r#" ("True 1", 2) -notcontains ($true, 1) "#)
.unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" (("True1", "1"), 2) -notcontains ($true, 1) "#)
.unwrap(),
"True".to_string()
);
assert_eq!(
p.safe_eval(r#" "3", "1" -notcontains 1 "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" "1" -notcontains 1 "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" "true", "1" -notcontains $true "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" "true", "1" -inotcontains $true "#).unwrap(),
"False".to_string()
);
assert_eq!(
p.safe_eval(r#" "true", "1" -cnotcontains $true "#).unwrap(),
"True".to_string()
);
}
}