use crate::{Apply, Core, Delta, DeltaResult, FromDelta, IntoDelta};
use std::fmt::Debug;
use serde::{Deserialize, Serialize};
impl<T> Core for Option<T>
where T: Clone + Debug + PartialEq + Core
+ for<'de> Deserialize<'de>
+ Serialize
{
type Delta = OptionDelta<T>;
}
impl<T> Apply for Option<T>
where T: Apply + FromDelta
+ for<'de> Deserialize<'de>
+ Serialize
{
fn apply(&self, delta: Self::Delta) -> DeltaResult<Self> {
Ok(match (&self, delta) {
(None, Self::Delta::None) => None,
(Some(_), Self::Delta::None) => self.clone(),
(None, Self::Delta::Some(ref d)) => Some(
<T>::from_delta(d.clone())?
),
(Some(t), Self::Delta::Some(ref d)) =>
Some(t.apply(d.clone())?),
})
}
}
impl<T> Delta for Option<T>
where T: Delta + IntoDelta
+ for<'de> Deserialize<'de>
+ Serialize
{
fn delta(&self, rhs: &Self) -> DeltaResult<Self::Delta> {
Ok(match (self, rhs) {
(Some(lhs), Some(rhs)) => Self::Delta::Some(lhs.delta(&rhs)?),
(None, Some(rhs)) => Self::Delta::Some(rhs.clone().into_delta()?),
(Some(_), None) => Self::Delta::None,
(None, None) => Self::Delta::None,
})
}
}
impl<T> FromDelta for Option<T>
where T: Clone + Debug + PartialEq + FromDelta
+ for<'de> Deserialize<'de>
+ Serialize
{
fn from_delta(delta: <Self as Core>::Delta) -> DeltaResult<Self> {
Ok(match delta {
Self::Delta::None => None,
Self::Delta::Some(delta) => Some(<T>::from_delta(delta)?),
})
}
}
impl<T> IntoDelta for Option<T>
where T: Clone + Debug + PartialEq + IntoDelta
+ for<'de> Deserialize<'de>
+ Serialize
{
fn into_delta(self) -> DeltaResult<<Self as Core>::Delta> {
Ok(match self {
Self::None => OptionDelta::None,
Self::Some(t) => OptionDelta::Some(t.into_delta()?),
})
}
}
#[derive(Clone, PartialEq)]
#[derive(serde_derive::Deserialize, serde_derive::Serialize)]
pub enum OptionDelta<T: Core> {
None,
Some(<T as Core>::Delta),
}
impl<T: Core> std::fmt::Debug for OptionDelta<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match &self {
Self::Some(d) => write!(f, "OptionDelta::Some({:#?})", d),
Self::None => write!(f, "OptionDelta::None"),
}
}
}
#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
use serde_json;
use super::*;
#[test]
fn Option__delta__same_values() -> DeltaResult<()> {
let foo = String::from("foo");
let bar = String::from("foo");
let option0 = Some(foo);
let option1 = Some(bar);
let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
let json_string = serde_json::to_string(&delta)
.expect("Could not serialize to json");
println!("json_string: \"{}\"", json_string);
assert_eq!(json_string, "{\"Some\":\"foo\"}");
let delta1: <Option<String> as Core>::Delta = serde_json::from_str(
&json_string
).expect("Could not deserialize from json");
assert_eq!(delta, delta1);
Ok(())
}
#[test]
fn Option__delta__different_values() -> DeltaResult<()> {
let foo = String::from("foo");
let bar = String::from("bar");
let option0 = Some(foo);
let option1 = Some(bar);
let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
let json_string = serde_json::to_string(&delta)
.expect("Could not serialize to json");
println!("json_string: \"{}\"", json_string);
assert_eq!(json_string, "{\"Some\":\"bar\"}");
let delta1: <Option<String> as Core>::Delta = serde_json::from_str(
&json_string
).expect("Could not deserialize from json");
assert_eq!(delta, delta1);
Ok(())
}
#[test]
fn Option__apply__same_values() -> DeltaResult<()> {
let foo = String::from("foo");
let bar = String::from("foo");
let option0 = Some(foo);
let option1 = Some(bar);
let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
let option2 = option0.apply(delta)?;
assert_eq!(option1, option2);
Ok(())
}
#[test]
fn Option__apply__different_values() -> DeltaResult<()> {
let foo = String::from("foo");
let bar = String::from("bar");
let option0 = Some(foo);
let option1 = Some(bar);
let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
let option2 = option0.apply(delta)?;
assert_eq!(option1, option2);
Ok(())
}
}