Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
360 lines
10 KiB
Rust
360 lines
10 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use compact_str::{CompactString, ToCompactString, format_compact};
|
|
use sha1::Sha1;
|
|
use sha2::{Sha256, Sha512};
|
|
use utils::HexEncode;
|
|
|
|
use crate::expr::{StringCow, Variable};
|
|
|
|
pub(crate) fn fn_trim(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0).transform(|s| match s {
|
|
StringCow::Borrowed(s) => Variable::from(s.trim()),
|
|
StringCow::Owned(s) => Variable::from(s.trim().to_compact_string()),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_trim_end(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0).transform(|s| match s {
|
|
StringCow::Borrowed(s) => Variable::from(s.trim_end()),
|
|
StringCow::Owned(s) => Variable::from(s.trim_end().to_compact_string()),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_trim_start(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0).transform(|s| match s {
|
|
StringCow::Borrowed(s) => Variable::from(s.trim_start()),
|
|
StringCow::Owned(s) => Variable::from(s.trim_start().to_compact_string()),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_len(v: Vec<Variable>) -> Variable {
|
|
match &v[0] {
|
|
Variable::String(s) => s.len(),
|
|
Variable::Array(a) => a.len(),
|
|
v => v.to_string().len(),
|
|
}
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_to_lowercase(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0)
|
|
.transform(|s| Variable::from(CompactString::from_str_to_lowercase(s.as_str())))
|
|
}
|
|
|
|
pub(crate) fn fn_to_uppercase(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0)
|
|
.transform(|s| Variable::from(CompactString::from_str_to_uppercase(s.as_str())))
|
|
}
|
|
|
|
pub(crate) fn fn_is_uppercase(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0).transform(|s| {
|
|
s.as_str()
|
|
.chars()
|
|
.filter(|c| c.is_alphabetic())
|
|
.all(|c| c.is_uppercase())
|
|
.into()
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_is_lowercase(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0).transform(|s| {
|
|
s.as_str()
|
|
.chars()
|
|
.filter(|c| c.is_alphabetic())
|
|
.all(|c| c.is_lowercase())
|
|
.into()
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_has_digits(mut v: Vec<Variable>) -> Variable {
|
|
v.remove(0)
|
|
.transform(|s| s.as_str().chars().any(|c| c.is_ascii_digit()).into())
|
|
}
|
|
|
|
pub(crate) fn fn_split_words(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.split_whitespace()
|
|
.filter(|word| word.chars().all(|c| c.is_alphanumeric()))
|
|
.map(|word| Variable::from(CompactString::new(word)))
|
|
.collect::<Vec<_>>()
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_count_spaces(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.chars()
|
|
.filter(|c| c.is_whitespace())
|
|
.count()
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_count_uppercase(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.chars()
|
|
.filter(|c| c.is_alphabetic() && c.is_uppercase())
|
|
.count()
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_count_lowercase(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.chars()
|
|
.filter(|c| c.is_alphabetic() && c.is_lowercase())
|
|
.count()
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_count_chars(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string().as_str().chars().count().into()
|
|
}
|
|
|
|
pub(crate) fn fn_eq_ignore_case(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.eq_ignore_ascii_case(v[1].to_string().as_str())
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_contains(v: Vec<Variable>) -> Variable {
|
|
match &v[0] {
|
|
Variable::String(s) => s.as_str().contains(v[1].to_string().as_str()),
|
|
Variable::Array(arr) => arr.contains(&v[1]),
|
|
val => val.to_string().as_str().contains(v[1].to_string().as_str()),
|
|
}
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_contains_ignore_case(v: Vec<Variable>) -> Variable {
|
|
let needle = v[1].to_string();
|
|
match &v[0] {
|
|
Variable::String(s) => s
|
|
.as_str()
|
|
.to_lowercase()
|
|
.contains(&needle.as_str().to_lowercase()),
|
|
Variable::Array(arr) => arr.iter().any(|v| match v {
|
|
Variable::String(s) => s.as_str().eq_ignore_ascii_case(needle.as_str()),
|
|
_ => false,
|
|
}),
|
|
val => val.to_string().as_str().contains(needle.as_str()),
|
|
}
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_starts_with(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.starts_with(v[1].to_string().as_str())
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_ends_with(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.ends_with(v[1].to_string().as_str())
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_lines(mut v: Vec<Variable>) -> Variable {
|
|
match v.remove(0) {
|
|
Variable::String(s) => s
|
|
.as_str()
|
|
.lines()
|
|
.map(|s| Variable::from(CompactString::new(s)))
|
|
.collect::<Vec<_>>()
|
|
.into(),
|
|
val => val,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fn_substring(v: Vec<Variable>) -> Variable {
|
|
v[0].to_string()
|
|
.as_str()
|
|
.chars()
|
|
.skip(v[1].to_usize().unwrap_or_default())
|
|
.take(v[2].to_usize().unwrap_or_default())
|
|
.collect::<CompactString>()
|
|
.into()
|
|
}
|
|
|
|
pub(crate) fn fn_strip_prefix(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap();
|
|
let prefix = v.next().unwrap().into_string();
|
|
|
|
value.transform(|s| match s {
|
|
StringCow::Borrowed(s) => s
|
|
.strip_prefix(prefix.as_str())
|
|
.map(Variable::from)
|
|
.unwrap_or_default(),
|
|
StringCow::Owned(s) => s
|
|
.strip_prefix(prefix.as_str())
|
|
.map(|s| Variable::from(CompactString::new(s)))
|
|
.unwrap_or_default(),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_strip_suffix(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap();
|
|
let suffix = v.next().unwrap().into_string();
|
|
|
|
value.transform(|s| match s {
|
|
StringCow::Borrowed(s) => s
|
|
.strip_suffix(suffix.as_str())
|
|
.map(Variable::from)
|
|
.unwrap_or_default(),
|
|
StringCow::Owned(s) => s
|
|
.strip_suffix(suffix.as_str())
|
|
.map(|s| Variable::from(CompactString::new(s)))
|
|
.unwrap_or_default(),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn fn_split(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let arg = v.next().unwrap().into_string();
|
|
|
|
match value {
|
|
StringCow::Borrowed(s) => s
|
|
.split(arg.as_str())
|
|
.map(Variable::from)
|
|
.collect::<Vec<_>>()
|
|
.into(),
|
|
StringCow::Owned(s) => s
|
|
.split(arg.as_str())
|
|
.map(|s| Variable::from(CompactString::new(s)))
|
|
.collect::<Vec<_>>()
|
|
.into(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fn_rsplit(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let arg = v.next().unwrap().into_string();
|
|
|
|
match value {
|
|
StringCow::Borrowed(s) => s
|
|
.rsplit(arg.as_str())
|
|
.map(Variable::from)
|
|
.collect::<Vec<_>>()
|
|
.into(),
|
|
StringCow::Owned(s) => s
|
|
.rsplit(arg.as_str())
|
|
.map(|s| Variable::from(CompactString::new(s)))
|
|
.collect::<Vec<_>>()
|
|
.into(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fn_split_n(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let arg = v.next().unwrap().into_string();
|
|
let num = v.next().unwrap().to_integer().unwrap_or_default() as usize;
|
|
|
|
fn split_n<'x, 'y>(s: &'x str, arg: &'y str, num: usize, mut f: impl FnMut(&'x str)) {
|
|
let mut s = s;
|
|
for _ in 0..num {
|
|
if let Some((a, b)) = s.split_once(arg) {
|
|
f(a);
|
|
s = b;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
f(s);
|
|
}
|
|
|
|
let mut result = Vec::new();
|
|
match value {
|
|
StringCow::Borrowed(s) => split_n(s, arg.as_str(), num, |s| result.push(Variable::from(s))),
|
|
StringCow::Owned(s) => split_n(&s, arg.as_str(), num, |s| {
|
|
result.push(Variable::from(CompactString::new(s)))
|
|
}),
|
|
}
|
|
|
|
result.into()
|
|
}
|
|
|
|
pub(crate) fn fn_split_once(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let arg = v.next().unwrap().into_string();
|
|
|
|
match value {
|
|
StringCow::Borrowed(s) => s
|
|
.split_once(arg.as_str())
|
|
.map(|(a, b)| Variable::Array(vec![Variable::from(a), Variable::from(b)]))
|
|
.unwrap_or_default(),
|
|
StringCow::Owned(s) => s
|
|
.split_once(arg.as_str())
|
|
.map(|(a, b)| {
|
|
Variable::Array(vec![
|
|
Variable::from(CompactString::new(a)),
|
|
Variable::from(CompactString::new(b)),
|
|
])
|
|
})
|
|
.unwrap_or_default(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fn_rsplit_once(v: Vec<Variable>) -> Variable {
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let arg = v.next().unwrap().into_string();
|
|
|
|
match value {
|
|
StringCow::Borrowed(s) => s
|
|
.rsplit_once(arg.as_str())
|
|
.map(|(a, b)| Variable::Array(vec![Variable::from(a), Variable::from(b)]))
|
|
.unwrap_or_default(),
|
|
StringCow::Owned(s) => s
|
|
.rsplit_once(arg.as_str())
|
|
.map(|(a, b)| {
|
|
Variable::Array(vec![
|
|
Variable::from(CompactString::new(a)),
|
|
Variable::from(CompactString::new(b)),
|
|
])
|
|
})
|
|
.unwrap_or_default(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fn_hash(v: Vec<Variable>) -> Variable {
|
|
use sha1::Digest;
|
|
let mut v = v.into_iter();
|
|
let value = v.next().unwrap().into_string();
|
|
let algo = v.next().unwrap().into_string();
|
|
|
|
match algo.as_str() {
|
|
"md5" => format_compact!("{:x}", md5::compute(value.as_bytes())).into(),
|
|
"sha1" => {
|
|
let mut hasher = Sha1::new();
|
|
hasher.update(value.as_bytes());
|
|
hasher.finalize().hex_encode().to_compact_string().into()
|
|
}
|
|
"sha256" => {
|
|
let mut hasher = Sha256::new();
|
|
hasher.update(value.as_bytes());
|
|
hasher.finalize().hex_encode().to_compact_string().into()
|
|
}
|
|
"sha512" => {
|
|
let mut hasher = Sha512::new();
|
|
hasher.update(value.as_bytes());
|
|
hasher.finalize().hex_encode().to_compact_string().into()
|
|
}
|
|
_ => Variable::default(),
|
|
}
|
|
}
|