use md5::Md5;
use sha2::{
digest::Output as SHA2DigestOutput, Digest as SHA2Digest, Sha224, Sha256, Sha384,
Sha512,
};
use crate::error::{DataFusionError, Result};
use arrow::array::{
ArrayRef, GenericBinaryArray, GenericStringArray, StringOffsetSizeTrait,
};
fn md5_process(input: &str) -> String {
let mut digest = Md5::default();
digest.update(&input);
let mut result = String::new();
for byte in &digest.finalize() {
result.push_str(&format!("{:02x}", byte));
}
result
}
fn sha_process<D: SHA2Digest + Default>(input: &str) -> SHA2DigestOutput<D> {
let mut digest = D::default();
digest.update(&input);
digest.finalize()
}
macro_rules! crypto_unary_string_function {
($NAME:ident, $FUNC:expr) => {
pub fn $NAME<T: StringOffsetSizeTrait>(
args: &[ArrayRef],
) -> Result<GenericStringArray<i32>> {
if args.len() != 1 {
return Err(DataFusionError::Internal(format!(
"{:?} args were supplied but {} takes exactly one argument",
args.len(),
String::from(stringify!($NAME)),
)));
}
let array = args[0]
.as_any()
.downcast_ref::<GenericStringArray<T>>()
.unwrap();
Ok(array.iter().map(|x| x.map(|x| $FUNC(x))).collect())
}
};
}
macro_rules! crypto_unary_binary_function {
($NAME:ident, $FUNC:expr) => {
pub fn $NAME<T: StringOffsetSizeTrait>(
args: &[ArrayRef],
) -> Result<GenericBinaryArray<i32>> {
if args.len() != 1 {
return Err(DataFusionError::Internal(format!(
"{:?} args were supplied but {} takes exactly one argument",
args.len(),
String::from(stringify!($NAME)),
)));
}
let array = args[0]
.as_any()
.downcast_ref::<GenericStringArray<T>>()
.unwrap();
Ok(array.iter().map(|x| x.map(|x| $FUNC(x))).collect())
}
};
}
crypto_unary_string_function!(md5, md5_process);
crypto_unary_binary_function!(sha224, sha_process::<Sha224>);
crypto_unary_binary_function!(sha256, sha_process::<Sha256>);
crypto_unary_binary_function!(sha384, sha_process::<Sha384>);
crypto_unary_binary_function!(sha512, sha_process::<Sha512>);