pub mod dns;
pub mod encoding;
pub mod geoip;
pub mod list;
pub mod network;
pub mod string_mutators;
use crate::error::{Result, TqlError};
use serde_json::Value as JsonValue;
use std::collections::HashMap;
pub trait Mutator: Send + Sync {
fn apply(&self, field_name: &str, record: &JsonValue, value: &JsonValue) -> Result<JsonValue>;
fn name(&self) -> &str;
fn is_enrichment(&self) -> bool {
false
}
}
pub type MutatorParams = HashMap<String, JsonValue>;
pub fn apply_mutators(
value: &JsonValue,
mutators: &[Box<dyn Mutator>],
field_name: &str,
record: &JsonValue,
) -> Result<JsonValue> {
let mut result = value.clone();
for mutator in mutators {
result = mutator.apply(field_name, record, &result)?;
}
Ok(result)
}
pub fn get_param<'a>(
params: &'a HashMap<String, JsonValue>,
named_key: &str,
positional_index: usize,
) -> Option<&'a JsonValue> {
params
.get(named_key)
.or_else(|| params.get(&positional_index.to_string()))
}
pub fn create_mutator(name: &str, params: Option<MutatorParams>) -> Result<Box<dyn Mutator>> {
let params = params.unwrap_or_default();
let name_lower = name.to_lowercase();
match name_lower.as_str() {
"lowercase" => Ok(Box::new(string_mutators::LowercaseMutator::new(params))),
"uppercase" => Ok(Box::new(string_mutators::UppercaseMutator::new(params))),
"trim" => Ok(Box::new(string_mutators::TrimMutator::new(params))),
"split" => Ok(Box::new(string_mutators::SplitMutator::new(params))),
"length" => Ok(Box::new(string_mutators::LengthMutator::new(params))),
"replace" => Ok(Box::new(string_mutators::ReplaceMutator::new(params))),
"b64encode" => Ok(Box::new(encoding::Base64EncodeMutator::new(params))),
"b64decode" => Ok(Box::new(encoding::Base64DecodeMutator::new(params))),
"urldecode" => Ok(Box::new(encoding::URLDecodeMutator::new(params))),
"hexencode" => Ok(Box::new(encoding::HexEncodeMutator::new(params))),
"hexdecode" => Ok(Box::new(encoding::HexDecodeMutator::new(params))),
"md5" => Ok(Box::new(encoding::MD5Mutator::new(params))),
"sha256" => Ok(Box::new(encoding::SHA256Mutator::new(params))),
"refang" => Ok(Box::new(network::RefangMutator::new(params))),
"defang" => Ok(Box::new(network::DefangMutator::new(params))),
"is_private" => Ok(Box::new(network::IsPrivateMutator::new(params))),
"is_global" => Ok(Box::new(network::IsGlobalMutator::new(params))),
"is_multicast" => Ok(Box::new(network::IsMulticastMutator::new(params))),
"is_loopback" => Ok(Box::new(network::IsLoopbackMutator::new(params))),
"is_link_local" => Ok(Box::new(network::IsLinkLocalMutator::new(params))),
"nslookup" => Ok(Box::new(dns::NSLookupMutator::new(params))),
"geoip" | "geoip_lookup" | "geo" => Ok(Box::new(geoip::GeoIPMutator::new(params))),
"any" => Ok(Box::new(list::AnyMutator::new(params))),
"all" => Ok(Box::new(list::AllMutator::new(params))),
"avg" => Ok(Box::new(list::AvgMutator::new(params))),
"average" => Ok(Box::new(list::AverageMutator::new(params))),
"sum" => Ok(Box::new(list::SumMutator::new(params))),
"max" => Ok(Box::new(list::MaxMutator::new(params))),
"min" => Ok(Box::new(list::MinMutator::new(params))),
_ => Err(TqlError::MutatorError(format!("Unknown mutator: {}", name))),
}
}