Skip to content

Commit

Permalink
Add blake2 and blake3 UDFs
Browse files Browse the repository at this point in the history
  • Loading branch information
tgross35 committed Oct 4, 2023
1 parent 206f1e4 commit b737c35
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
resolver = "2"
members = [
"udf-blake",
"udf-jsonify",
"udf-lipsum",
"udf-uuid",
Expand Down
79 changes: 79 additions & 0 deletions test-integration/tests/test_blake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#![cfg(feature = "backend")]

mod backend;

use backend::get_db_connection;
use mysql::prelude::*;

const SETUP: &[&str] = &[
"create or replace function blake2b512 returns string
soname 'libudf_blake.so'",
"create or replace function blake2s256 returns string
soname 'libudf_blake.so'",
"create or replace function blake3 returns string
soname 'libudf_blake.so'",
];

const TEST: &str = "Hello, world!";
const PARTS: (&str, &str, &str) = ("Hello, ", "world", "!");
const RESULT_B512: &str = "a2764d133a16816b5847a737a786f2ece4c148095c5faa73e24b4cc5d666c3e4\
5ec271504e14dc6127ddfce4e144fb23b91a6f7b04b53d695502290722953b0f";
const RESULT_S256: &str = "30d8777f0e178582ec8cd2fcdc18af57c828ee2f89e978df52c8e7af078bd5cf";
const RESULT_3: &str = "ede5c0b10f2ec4979c69b52f61e42ff5b413519ce09be0f14d098dcfe5f6f98d";

#[test]
fn test_blake2b512() {
let conn = &mut get_db_connection(SETUP);

let res: Vec<u8> = conn
.exec_first("select hex(blake2b512(?))", (TEST,))
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_B512);

let res: Vec<u8> = conn
.exec_first("select hex(blake2b512(?, ?, ?))", PARTS)
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_B512);
}

#[test]
fn test_blake2s256() {
let conn = &mut get_db_connection(SETUP);

let res: Vec<u8> = conn
.exec_first("select hex(blake2s256((?))", (TEST,))
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_S256);

let res: Vec<u8> = conn
.exec_first("select hex(blake2s256((?, ?, ?))", PARTS)
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_S256);
}

#[test]
fn test_blake3() {
let conn = &mut get_db_connection(SETUP);

let res: Vec<u8> = conn
.exec_first("select hex(blake3(?))", (TEST,))
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_3);

let res: Vec<u8> = conn
.exec_first("select hex(blake3(?, ?, ?))", PARTS)
.unwrap()
.unwrap();

assert_eq!(hex::encode(res), RESULT_3);
}
14 changes: 14 additions & 0 deletions udf-blake/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "udf-blake"
version = "0.1.7"
edition = "2021"
publish = false
license = "Apache-2.0 OR GPL-2.0-or-later"

[lib]
crate-type = ["cdylib"]

[dependencies]
blake2 = "0.10.6"
blake3 = "1.5.0"
udf = { version = "0.5.4", features = ["mock"] }
124 changes: 124 additions & 0 deletions udf-blake/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//! Blake2 and Blake3 hash algorithms
//!
//! # Usage
//!
//! ```sql
//! CREATE FUNCTION blake2b512 RETURNS string SONAME 'libudf_blake.so';
//! CREATE FUNCTION blake2s256 RETURNS string SONAME 'libudf_blake.so';
//! CREATE FUNCTION blake3 RETURNS string SONAME 'libudf_blake.so';
//!
//! SELECT blake2b512('Hello world!');
//! SELECT blake2s256('Hello world!');
//! SELECT blake3('Hello world!');
//! ```

use blake2::Digest;
use udf::prelude::*;

// We store our hashers to save a small bit of time
struct Blake2b512 {
hasher: blake2::Blake2b512,
ret: [u8; 64],
}

struct Blake2s256 {
hasher: blake2::Blake2s256,
ret: [u8; 32],
}

struct Blake3 {
hasher: blake3::Hasher,
ret: [u8; 32],
}

#[register(name = "blake2b512")]
impl BasicUdf for Blake2b512 {
type Returns<'a> = &'a [u8];

fn init(_cfg: &UdfCfg<Init>, _args: &ArgList<Init>) -> Result<Self, String> {
let ret = Self {
hasher: blake2::Blake2b512::new(),
ret: [0u8; 64],
};
Ok(ret)
}

fn process<'a>(
&'a mut self,
_cfg: &UdfCfg<Process>,
args: &ArgList<Process>,
_error: Option<NonZeroU8>,
) -> Result<Self::Returns<'a>, ProcessError> {
args.iter()
.for_each(|arg| hash_arg(arg, |buf| self.hasher.update(buf)));
self.hasher.finalize_into_reset(&mut self.ret.into());
Ok(&self.ret)
}
}

#[register(name = "blake2s256")]
impl BasicUdf for Blake2s256 {
type Returns<'a> = &'a [u8];

fn init(_cfg: &UdfCfg<Init>, _args: &ArgList<Init>) -> Result<Self, String> {
let ret = Self {
hasher: blake2::Blake2s256::new(),
ret: [0u8; 32],
};
Ok(ret)
}

fn process<'a>(
&'a mut self,
_cfg: &UdfCfg<Process>,
args: &ArgList<Process>,
_error: Option<NonZeroU8>,
) -> Result<Self::Returns<'a>, ProcessError> {
args.iter()
.for_each(|arg| hash_arg(arg, |buf| self.hasher.update(buf)));
self.hasher.finalize_into_reset(&mut self.ret.into());
Ok(&self.ret)
}
}

#[register(name = "blake3")]
impl BasicUdf for Blake3 {
type Returns<'a> = &'a [u8];

fn init(_cfg: &UdfCfg<Init>, _args: &ArgList<Init>) -> Result<Self, String> {
let ret = Self {
hasher: blake3::Hasher::new(),
ret: [0u8; 32],
};
Ok(ret)
}

fn process<'a>(
&'a mut self,
_cfg: &UdfCfg<Process>,
args: &ArgList<Process>,
_error: Option<NonZeroU8>,
) -> Result<Self::Returns<'a>, ProcessError> {
args.iter().for_each(|arg| {
hash_arg(arg, |buf| {
self.hasher.update(buf);
})
});
let hash = self.hasher.finalize();
self.ret = hash.into();
self.hasher.reset();
Ok(&self.ret)
}
}

/// Turn a SQL argument into a hashable buffer and pass it the given function
fn hash_arg<T>(arg: SqlArg<Process>, mut hash_fn: impl FnMut(&[u8]) -> T) -> T {
// Any non-null value will update the hash, null values do nothing.
match arg.value() {
SqlResult::String(Some(buf)) => hash_fn(buf),
SqlResult::Real(Some(f)) => hash_fn(&f.to_le_bytes()),
SqlResult::Int(Some(i)) => hash_fn(&i.to_le_bytes()),
SqlResult::Decimal(Some(d)) => hash_fn(d.as_bytes()),
_ => hash_fn([].as_slice()),
}
}
2 changes: 1 addition & 1 deletion udf-xxhash/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! A function to generate lipsum of a given word count
//! A function to generate the xxhash of any input
//!
//! # Usage
//!
Expand Down

0 comments on commit b737c35

Please sign in to comment.