use digest::Digest;
use rusqlite::{Connection, Error, functions::FunctionFlags};
fn mkhasher(algo: &str) -> Result<Box<dyn digest::DynDigest>, Error> {
match algo {
"sha2/224" => Ok(Box::new(sha2::Sha224::new())),
"sha2/256" => Ok(Box::new(sha2::Sha256::new())),
"sha2/384" => Ok(Box::new(sha2::Sha384::new())),
"sha2/512" => Ok(Box::new(sha2::Sha512::new())),
"sha3/224" => Ok(Box::new(sha3::Sha3_224::new())),
"sha3/256" => Ok(Box::new(sha3::Sha3_256::new())),
"sha3/384" => Ok(Box::new(sha3::Sha3_384::new())),
"sha3/512" => Ok(Box::new(sha3::Sha3_512::new())),
_ => Err(Error::UserFunctionError("Bad hash algo".into()))?
}
}
#[allow(clippy::missing_errors_doc)]
pub fn hashstr(conn: &Connection) -> Result<(), Error> {
conn.create_scalar_function(
"hashstr",
2,
FunctionFlags::SQLITE_UTF8
| FunctionFlags::SQLITE_INNOCUOUS
| FunctionFlags::SQLITE_DETERMINISTIC,
move |ctx| {
let algo = ctx.get::<String>(0)?.to_lowercase();
let s = ctx.get::<String>(1)?;
let mut hasher = mkhasher(algo.as_ref())?;
hasher.update(s.as_bytes());
let result = hasher.finalize();
Ok(result[..].to_vec())
}
)
}
#[allow(clippy::missing_errors_doc)]
pub fn hashblob(conn: &Connection) -> Result<(), Error> {
conn.create_scalar_function(
"hashblob",
2,
FunctionFlags::SQLITE_UTF8
| FunctionFlags::SQLITE_INNOCUOUS
| FunctionFlags::SQLITE_DETERMINISTIC,
move |ctx| {
let algo = ctx.get::<String>(0)?.to_lowercase();
let blob = ctx.get::<Vec<u8>>(1)?;
let mut hasher = mkhasher(algo.as_ref())?;
hasher.update(&blob);
let result = hasher.finalize();
Ok(result[..].to_vec())
}
)
}