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 (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u16::from_le_bytes(a_bytes);
let b = u16::from_le_bytes(b_bytes);
a.wrapping_add(b).to_le_bytes().to_vec()
}
4 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u32::from_le_bytes(a_bytes);
let b = u32::from_le_bytes(b_bytes);
a.wrapping_add(b).to_le_bytes().to_vec()
}
8 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u64::from_le_bytes(a_bytes);
let b = u64::from_le_bytes(b_bytes);
a.wrapping_add(b).to_le_bytes().to_vec()
}
_ => return Some(existing.to_vec()),
};
Some(result)
}
}
#[derive(Clone, Copy)]
pub struct SaturatingAdd;
impl Debug for SaturatingAdd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("SaturatingAdd")
}
}
impl MergeOperator for SaturatingAdd {
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.saturating_add(b)]
}
2 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u16::from_le_bytes(a_bytes);
let b = u16::from_le_bytes(b_bytes);
a.saturating_add(b).to_le_bytes().to_vec()
}
4 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u32::from_le_bytes(a_bytes);
let b = u32::from_le_bytes(b_bytes);
a.saturating_add(b).to_le_bytes().to_vec()
}
8 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u64::from_le_bytes(a_bytes);
let b = u64::from_le_bytes(b_bytes);
a.saturating_add(b).to_le_bytes().to_vec()
}
_ => return Some(existing.to_vec()),
};
Some(result)
}
}
#[derive(Clone, Copy)]
pub struct FloatAdd;
impl Debug for FloatAdd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("FloatAdd")
}
}
impl MergeOperator for FloatAdd {
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() {
4 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = f32::from_le_bytes(a_bytes);
let b = f32::from_le_bytes(b_bytes);
(a + b).to_le_bytes().to_vec()
}
8 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = f64::from_le_bytes(a_bytes);
let b = f64::from_le_bytes(b_bytes);
(a + 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 (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u16::from_le_bytes(a_bytes);
let b = u16::from_le_bytes(b_bytes);
b > a
}
4 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u32::from_le_bytes(a_bytes);
let b = u32::from_le_bytes(b_bytes);
b > a
}
8 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u64::from_le_bytes(a_bytes);
let b = u64::from_le_bytes(b_bytes);
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 (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u16::from_le_bytes(a_bytes);
let b = u16::from_le_bytes(b_bytes);
b < a
}
4 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u32::from_le_bytes(a_bytes);
let b = u32::from_le_bytes(b_bytes);
b < a
}
8 => {
let (Ok(a_bytes), Ok(b_bytes)) = (existing.try_into(), operand.try_into()) else {
return Some(existing.to_vec());
};
let a = u64::from_le_bytes(a_bytes);
let b = u64::from_le_bytes(b_bytes);
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 }
}