use super::Codec;
use std::marker::PhantomData;
use std::ops::Sub;
#[derive(Clone, Debug)]
pub enum FieldOperatorInstruction {
Constant,
None,
Delta,
Tail,
Copy,
}
pub trait FieldOperator {
type Item: Codec;
fn previous_value(&self) -> Option<&Self::Item>;
fn replace(&mut self, new_value: Self::Item);
fn can_omit(&self, value: &Self::Item) -> bool;
fn reset(&mut self);
}
#[derive(Debug)]
pub struct Constant<T> {
value: T,
}
impl<T> Constant<T> {
pub fn new(value: T) -> Self {
Constant { value }
}
}
impl<T> FieldOperator for Constant<T>
where
T: Codec,
{
type Item = T;
fn previous_value(&self) -> Option<&T> {
Some(&self.value)
}
fn can_omit(&self, _value: &T) -> bool {
true
}
fn replace(&mut self, _new_value: T) {}
fn reset(&mut self) {}
}
#[derive(Debug)]
pub struct Delta<T, U> {
prev: Option<T>,
delta: U,
}
impl<U, T> FieldOperator for Delta<T, U>
where
U: PartialEq,
T: Codec + Sub<Output = U> + std::marker::Copy,
{
type Item = T;
fn previous_value(&self) -> Option<&T> {
self.prev.as_ref()
}
fn can_omit(&self, value: &T) -> bool {
if let Some(prev) = self.prev {
*value - prev == self.delta
} else {
false
}
}
fn replace(&mut self, new_value: T) {
self.prev = Some(new_value)
}
fn reset(&mut self) {
self.prev = Option::None
}
}
#[derive(Debug)]
pub struct Copy<T> {
prev: Option<T>,
}
impl<T> FieldOperator for Copy<T>
where
T: Codec + PartialEq + std::marker::Copy,
{
type Item = T;
fn previous_value(&self) -> Option<&T> {
self.prev.as_ref()
}
fn can_omit(&self, value: &T) -> bool {
if let Some(previous_value) = self.previous_value() {
value == previous_value
} else {
false
}
}
fn replace(&mut self, new_value: T) {
self.prev = Some(new_value)
}
fn reset(&mut self) {
self.prev = Option::None
}
}
#[derive(Debug)]
pub struct None<T>(PhantomData<T>);
impl<T> Default for None<T> {
fn default() -> Self {
None(PhantomData)
}
}
impl<T> FieldOperator for None<T>
where
T: Codec,
{
type Item = T;
fn previous_value(&self) -> Option<&T> {
Option::None
}
fn can_omit(&self, _value: &T) -> bool {
false
}
fn replace(&mut self, _new_value: T) {}
fn reset(&mut self) {}
}