1use crate::{Apply, Core, Delta, DeltaResult, FromDelta, IntoDelta};
4use std::fmt::Debug;
5use serde::{Deserialize, Serialize};
6
7impl<T> Core for Option<T>
8where T: Clone + Debug + PartialEq + Core
9 + for<'de> Deserialize<'de>
10 + Serialize
11{
12 type Delta = OptionDelta<T>;
13}
14
15impl<T> Apply for Option<T>
16where T: Apply + FromDelta
17 + for<'de> Deserialize<'de>
18 + Serialize
19{
20 fn apply(&self, delta: Self::Delta) -> DeltaResult<Self> {
21 Ok(match (&self, delta) {
22 (None, Self::Delta::None) => None,
23 (Some(_), Self::Delta::None) => self.clone(),
24 (None, Self::Delta::Some(ref d)) => Some(
25 <T>::from_delta(d.clone())?
26 ),
27 (Some(t), Self::Delta::Some(ref d)) =>
28 Some(t.apply(d.clone())?),
29 })
30 }
31}
32
33impl<T> Delta for Option<T>
34where T: Delta + IntoDelta
35 + for<'de> Deserialize<'de>
36 + Serialize
37{
38 fn delta(&self, rhs: &Self) -> DeltaResult<Self::Delta> {
39 Ok(match (self, rhs) {
40 (Some(lhs), Some(rhs)) => Self::Delta::Some(lhs.delta(&rhs)?),
41 (None, Some(rhs)) => Self::Delta::Some(rhs.clone().into_delta()?),
42 (Some(_), None) => Self::Delta::None,
43 (None, None) => Self::Delta::None,
44 })
45 }
46}
47
48impl<T> FromDelta for Option<T>
49where T: Clone + Debug + PartialEq + FromDelta
50 + for<'de> Deserialize<'de>
51 + Serialize
52{
53 fn from_delta(delta: <Self as Core>::Delta) -> DeltaResult<Self> {
54 Ok(match delta {
55 Self::Delta::None => None,
56 Self::Delta::Some(delta) => Some(<T>::from_delta(delta)?),
57 })
58 }
59}
60
61impl<T> IntoDelta for Option<T>
62where T: Clone + Debug + PartialEq + IntoDelta
63 + for<'de> Deserialize<'de>
64 + Serialize
65{
66 fn into_delta(self) -> DeltaResult<<Self as Core>::Delta> {
67 Ok(match self {
68 Self::None => OptionDelta::None,
69 Self::Some(t) => OptionDelta::Some(t.into_delta()?),
70 })
71 }
72}
73
74
75
76#[derive(Clone, PartialEq)]
77#[derive(serde_derive::Deserialize, serde_derive::Serialize)]
78pub enum OptionDelta<T: Core> {
79 None,
80 Some(<T as Core>::Delta),
81}
82
83impl<T: Core> std::fmt::Debug for OptionDelta<T> {
84 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
85 match &self {
86 Self::Some(d) => write!(f, "OptionDelta::Some({:#?})", d),
87 Self::None => write!(f, "OptionDelta::None"),
88 }
89 }
90}
91
92
93#[allow(non_snake_case)]
94#[cfg(test)]
95mod tests {
96 use serde_json;
97 use super::*;
98
99 #[test]
100 fn Option__delta__same_values() -> DeltaResult<()> {
101 let foo = String::from("foo");
102 let bar = String::from("foo");
103 let option0 = Some(foo);
104 let option1 = Some(bar);
105 let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
106 let json_string = serde_json::to_string(&delta)
107 .expect("Could not serialize to json");
108 println!("json_string: \"{}\"", json_string);
109 assert_eq!(json_string, "{\"Some\":\"foo\"}");
110 let delta1: <Option<String> as Core>::Delta = serde_json::from_str(
111 &json_string
112 ).expect("Could not deserialize from json");
113 assert_eq!(delta, delta1);
114 Ok(())
115 }
116
117 #[test]
118 fn Option__delta__different_values() -> DeltaResult<()> {
119 let foo = String::from("foo");
120 let bar = String::from("bar");
121 let option0 = Some(foo);
122 let option1 = Some(bar);
123 let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
124 let json_string = serde_json::to_string(&delta)
125 .expect("Could not serialize to json");
126 println!("json_string: \"{}\"", json_string);
127 assert_eq!(json_string, "{\"Some\":\"bar\"}");
128 let delta1: <Option<String> as Core>::Delta = serde_json::from_str(
129 &json_string
130 ).expect("Could not deserialize from json");
131 assert_eq!(delta, delta1);
132 Ok(())
133 }
134
135 #[test]
136 fn Option__apply__same_values() -> DeltaResult<()> {
137 let foo = String::from("foo");
138 let bar = String::from("foo");
139 let option0 = Some(foo);
140 let option1 = Some(bar);
141 let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
142 let option2 = option0.apply(delta)?;
143 assert_eq!(option1, option2);
144 Ok(())
145 }
146
147 #[test]
148 fn Option__apply__different_values() -> DeltaResult<()> {
149 let foo = String::from("foo");
150 let bar = String::from("bar");
151 let option0 = Some(foo);
152 let option1 = Some(bar);
153 let delta: <Option<String> as Core>::Delta = option0.delta(&option1)?;
154 let option2 = option0.apply(delta)?;
155 assert_eq!(option1, option2);
156 Ok(())
157 }
158}