use super::*;
use std::marker::PhantomData;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Mutation<K, V> {
Null,
Remove,
Insert(K, V),
Update(V),
}
impl<K, V> Mutation<K, V> {
pub fn normalize(self, is_empty: bool) -> Mutation<K, V> {
use Mutation::*;
match (self, is_empty) {
(Null, _) | (Remove, true) | (Update(_), true) | (Insert(_, _), false) => Null,
(mutation, _) => mutation,
}
}
pub fn is_null(&self) -> bool {
matches!(self, Mutation::Null)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum UnaryMutatorKind {
Null,
Delete,
General,
}
pub trait UnaryTransformer<K, I, O> {
fn transform(&mut self, key: &K, value: &I) -> Option<O>;
}
pub trait UnaryMutator<K, V>: UnaryTransformer<K, V, V> {
#[inline(always)]
fn kind(&mut self) -> UnaryMutatorKind {
UnaryMutatorKind::General
}
#[inline(always)]
fn mutate(&mut self, key: &K, value: &V) -> UnaryResult<Option<V>> {
UnaryResult::New(self.transform(key, value))
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct NullMutator;
impl<K, V: Clone> UnaryTransformer<K, V, V> for NullMutator {
#[inline(always)]
fn transform(&mut self, _key: &K, value: &V) -> Option<V> {
Some(value.clone())
}
}
impl<K, V: Clone> UnaryMutator<K, V> for NullMutator {
#[inline(always)]
fn kind(&mut self) -> UnaryMutatorKind {
UnaryMutatorKind::Null
}
#[inline(always)]
fn mutate(&mut self, _key: &K, _value: &V) -> UnaryResult<Option<V>> {
UnaryResult::Old
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct DeleteMutator;
impl<K, I, O> UnaryTransformer<K, I, O> for DeleteMutator {
#[inline(always)]
fn transform(&mut self, _key: &K, _value: &I) -> Option<O> {
None
}
}
impl<K, V> UnaryMutator<K, V> for DeleteMutator {
#[inline(always)]
fn kind(&mut self) -> UnaryMutatorKind {
UnaryMutatorKind::Delete
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FilterMap<F, K, I, O> {
pub func: F,
key_type: PhantomData<K>,
input_type: PhantomData<I>,
output_type: PhantomData<O>,
}
impl<F, K, I, O> FilterMap<F, K, I, Option<O>> {
pub fn new(func: F) -> FilterMap<F, K, I, Option<O>>
where
F: FnMut(&K, &I) -> Option<O>,
{
FilterMap {
func,
key_type: PhantomData,
input_type: PhantomData,
output_type: PhantomData,
}
}
}
impl<F, K, V> FilterMap<F, K, V, UnaryResult<Option<V>>> {
pub fn annotated(func: F) -> FilterMap<F, K, V, UnaryResult<Option<V>>>
where
F: FnMut(&K, &V) -> UnaryResult<Option<V>>,
{
FilterMap {
func,
key_type: PhantomData,
input_type: PhantomData,
output_type: PhantomData,
}
}
}
impl<F, K, I, O> UnaryTransformer<K, I, O> for FilterMap<F, K, I, Option<O>>
where
F: FnMut(&K, &I) -> Option<O>,
{
#[inline(always)]
fn transform(&mut self, key: &K, value: &I) -> Option<O> {
(self.func)(key, value)
}
}
impl<F, K, V> UnaryTransformer<K, V, V> for FilterMap<F, K, V, UnaryResult<Option<V>>>
where
F: FnMut(&K, &V) -> UnaryResult<Option<V>>,
V: Clone,
{
#[inline(always)]
fn transform(&mut self, key: &K, value: &V) -> Option<V> {
match (self.func)(key, value) {
UnaryResult::Old => Some(value.clone()),
UnaryResult::New(n) => n,
}
}
}
impl<F, K, V> UnaryMutator<K, V> for FilterMap<F, K, V, Option<V>>
where
F: FnMut(&K, &V) -> Option<V>,
{
#[inline(always)]
fn kind(&mut self) -> UnaryMutatorKind {
UnaryMutatorKind::General
}
}
impl<F, K, V> UnaryMutator<K, V> for FilterMap<F, K, V, UnaryResult<Option<V>>>
where
V: Clone,
F: FnMut(&K, &V) -> UnaryResult<Option<V>>,
{
#[inline(always)]
fn kind(&mut self) -> UnaryMutatorKind {
UnaryMutatorKind::General
}
#[inline(always)]
fn mutate(&mut self, key: &K, value: &V) -> UnaryResult<Option<V>> {
(self.func)(key, value)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum BinaryMutatorKind {
Idempotent,
Nilpotent,
Left,
Right,
Ambi,
General,
}
pub trait BinaryTransformer<K, L, R, O> {
fn transform_bin(&mut self, key: &K, left: &L, right: &R) -> Option<O>;
}
pub trait BinaryMutator<K, V>: BinaryTransformer<K, V, V, V> {
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::General
}
#[inline(always)]
fn mutate_bin(&mut self, key: &K, left: &V, right: &V) -> BinaryResult<Option<V>> {
BinaryResult::New(self.transform_bin(key, left, right))
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct LeftAgreeMutator;
impl<K, L, R> BinaryTransformer<K, L, R, L> for LeftAgreeMutator
where
L: PartialEq<R> + Clone,
{
fn transform_bin(&mut self, _key: &K, left: &L, right: &R) -> Option<L> {
if left == right {
Some(left.clone())
} else {
None
}
}
}
impl<K, V> BinaryMutator<K, V> for LeftAgreeMutator
where
V: PartialEq + Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Idempotent
}
#[inline(always)]
fn mutate_bin(&mut self, _key: &K, left: &V, right: &V) -> BinaryResult<Option<V>> {
if left == right {
BinaryResult::Left
} else {
BinaryResult::New(None)
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct RightAgreeMutator;
impl<K, L, R> BinaryTransformer<K, L, R, R> for RightAgreeMutator
where
R: PartialEq<L> + Clone,
{
fn transform_bin(&mut self, _key: &K, left: &L, right: &R) -> Option<R> {
if right == left {
Some(right.clone())
} else {
None
}
}
}
impl<K, V> BinaryMutator<K, V> for RightAgreeMutator
where
V: PartialEq + Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Idempotent
}
#[inline(always)]
fn mutate_bin(&mut self, _key: &K, left: &V, right: &V) -> BinaryResult<Option<V>> {
if right == left {
BinaryResult::Right
} else {
BinaryResult::New(None)
}
}
}
impl<K, L, R, O> BinaryTransformer<K, L, R, O> for DeleteMutator {
#[inline(always)]
fn transform_bin(&mut self, _key: &K, _left: &L, _right: &R) -> Option<O> {
None
}
}
impl<K, V> BinaryMutator<K, V> for DeleteMutator
where
V: Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Nilpotent
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct LeftMutator;
impl<K, L, R> BinaryTransformer<K, L, R, L> for LeftMutator
where
L: Clone,
{
#[inline(always)]
fn transform_bin(&mut self, _key: &K, left: &L, _right: &R) -> Option<L> {
Some(left.clone())
}
}
impl<K, V> BinaryMutator<K, V> for LeftMutator
where
V: Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Left
}
#[inline(always)]
fn mutate_bin(&mut self, _key: &K, _left: &V, _right: &V) -> BinaryResult<Option<V>> {
BinaryResult::Left
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct RightMutator;
impl<K, L, R> BinaryTransformer<K, L, R, R> for RightMutator
where
R: Clone,
{
fn transform_bin(&mut self, _key: &K, _left: &L, right: &R) -> Option<R> {
Some(right.clone())
}
}
impl<K, V> BinaryMutator<K, V> for RightMutator
where
V: Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Right
}
#[inline(always)]
fn mutate_bin(&mut self, _key: &K, _left: &V, _right: &V) -> BinaryResult<Option<V>> {
BinaryResult::Right
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct AmbiMutator;
impl<K, L, R> BinaryTransformer<K, L, R, L> for AmbiMutator
where
L: Clone,
{
fn transform_bin(&mut self, _key: &K, left: &L, _right: &R) -> Option<L> {
Some(left.clone())
}
}
impl<K, V> BinaryMutator<K, V> for AmbiMutator
where
V: Clone,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
BinaryMutatorKind::Ambi
}
#[inline(always)]
fn mutate_bin(&mut self, _key: &K, _left: &V, _right: &V) -> BinaryResult<Option<V>> {
BinaryResult::Ambi
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, RefCast)]
#[repr(transparent)]
pub struct Swapped<B>(pub B);
impl<B, K, L, R, O> BinaryTransformer<K, L, R, O> for Swapped<B>
where
B: BinaryTransformer<K, R, L, O>,
{
fn transform_bin(&mut self, key: &K, left: &L, right: &R) -> Option<O> {
self.0.transform_bin(key, right, left)
}
}
impl<B, K, V> BinaryMutator<K, V> for Swapped<B>
where
B: BinaryMutator<K, V>,
{
#[inline(always)]
fn kind(&mut self) -> BinaryMutatorKind {
self.0.kind()
}
#[inline(always)]
fn mutate_bin(&mut self, key: &K, left: &V, right: &V) -> BinaryResult<Option<V>> {
self.0.mutate_bin(key, left, right).swap_sides()
}
}