use alloc::vec;
use alloc::vec::Vec;
use core::fmt::{self, Debug};
pub trait MergeOperator: Send + Sync {
fn merge(&self, key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>>;
}
#[derive(Clone, Copy)]
pub struct NumericAdd;
impl Debug for NumericAdd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("NumericAdd")
}
}
impl MergeOperator for NumericAdd {
fn merge(&self, _key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
let Some(existing) = existing else {
return Some(operand.to_vec());
};
if existing.len() != operand.len() {
return Some(existing.to_vec());
}
let result = match operand.len() {
1 => {
let a = existing[0];
let b = operand[0];
vec![a.wrapping_add(b)]
}
2 => {
let a = u16::from_le_bytes(existing.try_into().unwrap());
let b = u16::from_le_bytes(operand.try_into().unwrap());
a.wrapping_add(b).to_le_bytes().to_vec()
}
4 => {
let a = u32::from_le_bytes(existing.try_into().unwrap());
let b = u32::from_le_bytes(operand.try_into().unwrap());
a.wrapping_add(b).to_le_bytes().to_vec()
}
8 => {
let a = u64::from_le_bytes(existing.try_into().unwrap());
let b = u64::from_le_bytes(operand.try_into().unwrap());
a.wrapping_add(b).to_le_bytes().to_vec()
}
_ => return Some(existing.to_vec()),
};
Some(result)
}
}
#[derive(Clone, Copy)]
pub struct NumericMax;
impl Debug for NumericMax {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("NumericMax")
}
}
impl MergeOperator for NumericMax {
fn merge(&self, _key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
let Some(existing) = existing else {
return Some(operand.to_vec());
};
if existing.len() != operand.len() {
return Some(existing.to_vec());
}
let use_operand = match operand.len() {
1 => operand[0] > existing[0],
2 => {
let a = u16::from_le_bytes(existing.try_into().unwrap());
let b = u16::from_le_bytes(operand.try_into().unwrap());
b > a
}
4 => {
let a = u32::from_le_bytes(existing.try_into().unwrap());
let b = u32::from_le_bytes(operand.try_into().unwrap());
b > a
}
8 => {
let a = u64::from_le_bytes(existing.try_into().unwrap());
let b = u64::from_le_bytes(operand.try_into().unwrap());
b > a
}
_ => return Some(existing.to_vec()),
};
if use_operand {
Some(operand.to_vec())
} else {
Some(existing.to_vec())
}
}
}
#[derive(Clone, Copy)]
pub struct NumericMin;
impl Debug for NumericMin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("NumericMin")
}
}
impl MergeOperator for NumericMin {
fn merge(&self, _key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
let Some(existing) = existing else {
return Some(operand.to_vec());
};
if existing.len() != operand.len() {
return Some(existing.to_vec());
}
let use_operand = match operand.len() {
1 => operand[0] < existing[0],
2 => {
let a = u16::from_le_bytes(existing.try_into().unwrap());
let b = u16::from_le_bytes(operand.try_into().unwrap());
b < a
}
4 => {
let a = u32::from_le_bytes(existing.try_into().unwrap());
let b = u32::from_le_bytes(operand.try_into().unwrap());
b < a
}
8 => {
let a = u64::from_le_bytes(existing.try_into().unwrap());
let b = u64::from_le_bytes(operand.try_into().unwrap());
b < a
}
_ => return Some(existing.to_vec()),
};
if use_operand {
Some(operand.to_vec())
} else {
Some(existing.to_vec())
}
}
}
#[derive(Clone, Copy)]
pub struct BitwiseOr;
impl Debug for BitwiseOr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("BitwiseOr")
}
}
impl MergeOperator for BitwiseOr {
fn merge(&self, _key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
let Some(existing) = existing else {
return Some(operand.to_vec());
};
if existing.len() != operand.len() {
return Some(existing.to_vec());
}
let result: Vec<u8> = existing
.iter()
.zip(operand.iter())
.map(|(a, b)| a | b)
.collect();
Some(result)
}
}
#[derive(Clone, Copy)]
pub struct BytesAppend;
impl Debug for BytesAppend {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("BytesAppend")
}
}
impl MergeOperator for BytesAppend {
fn merge(&self, _key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
let Some(existing) = existing else {
return Some(operand.to_vec());
};
let mut result = Vec::with_capacity(existing.len() + operand.len());
result.extend_from_slice(existing);
result.extend_from_slice(operand);
Some(result)
}
}
pub struct FnMergeOperator<F>
where
F: Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>> + Send + Sync,
{
f: F,
}
impl<F> Debug for FnMergeOperator<F>
where
F: Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>> + Send + Sync,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("FnMergeOperator")
}
}
impl<F> MergeOperator for FnMergeOperator<F>
where
F: Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>> + Send + Sync,
{
fn merge(&self, key: &[u8], existing: Option<&[u8]>, operand: &[u8]) -> Option<Vec<u8>> {
(self.f)(key, existing, operand)
}
}
pub fn merge_fn<F>(f: F) -> FnMergeOperator<F>
where
F: Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>> + Send + Sync,
{
FnMergeOperator { f }
}