use crate::types::Value;
pub fn wildcard_match_value(pattern: &Value, text: &Value) -> bool {
let (pat_str, txt_str) = match (pattern, text) {
(Value::Text(p), Value::Text(t)) => (p.to_lowercase(), t.to_lowercase()),
_ => return false,
};
let pat: Vec<char> = pat_str.chars().collect();
let txt: Vec<char> = txt_str.chars().collect();
wildcard_match_chars(&pat, &txt)
}
fn wildcard_match_chars(pattern: &[char], text: &[char]) -> bool {
match (pattern.first(), text.first()) {
(None, None) => true,
(None, _) => false,
(Some('*'), _) => {
for i in 0..=text.len() {
if wildcard_match_chars(&pattern[1..], &text[i..]) {
return true;
}
}
false
}
(Some(_), None) => false,
(Some(p), Some(t)) => {
if *p == '?' || *p == *t {
wildcard_match_chars(&pattern[1..], &text[1..])
} else {
false
}
}
}
}
pub fn has_wildcards(v: &Value) -> bool {
match v {
Value::Text(s) => s.contains('*') || s.contains('?'),
_ => false,
}
}
pub fn flatten_to_rows(v: &Value) -> Vec<Vec<Value>> {
match v {
Value::Array(outer) => {
let is_2d = outer.iter().any(|e| matches!(e, Value::Array(_)));
if is_2d {
outer.iter().map(|row| match row {
Value::Array(cols) => cols.clone(),
other => vec![other.clone()],
}).collect()
} else {
vec![outer.clone()]
}
}
other => vec![vec![other.clone()]],
}
}
pub fn flatten_to_flat(v: &Value) -> Vec<Value> {
match v {
Value::Array(elems) => elems.iter().flat_map(flatten_to_flat).collect(),
other => vec![other.clone()],
}
}
pub fn values_equal(a: &Value, b: &Value) -> bool {
match (a, b) {
(Value::Number(x), Value::Number(y)) => x == y,
(Value::Bool(x), Value::Bool(y)) => x == y,
(Value::Text(x), Value::Text(y)) => x.to_uppercase() == y.to_uppercase(),
(Value::Empty, Value::Empty) => true,
_ => false,
}
}
pub fn value_compare(a: &Value, b: &Value) -> Option<std::cmp::Ordering> {
match (a, b) {
(Value::Number(x), Value::Number(y)) => x.partial_cmp(y),
(Value::Text(x), Value::Text(y)) => Some(x.to_uppercase().cmp(&y.to_uppercase())),
_ => None,
}
}