1use crate::{
2 dif::{DIFConvertible, value::DIFValueContainer},
3 shared_values::observers::TransceiverId,
4 values::value_container::ValueKey,
5};
6use core::prelude::rust_2024::*;
7use serde::{Deserialize, Serialize};
8
9use crate::prelude::*;
10#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
12#[serde(tag = "kind", rename_all = "lowercase", content = "value")]
13pub enum DIFKey {
14 Text(String),
16 Index(i64),
19 Value(DIFValueContainer),
21}
22
23impl DIFKey {
24 pub fn from_value_key(key: &ValueKey) -> Self {
25 match key {
26 ValueKey::Text(s) => DIFKey::Text(s.to_string()),
27 ValueKey::Index(i) => DIFKey::Index(*i),
28 ValueKey::Value(v) => {
29 DIFKey::Value(DIFValueContainer::from_value_container(v))
30 }
31 }
32 }
33}
34
35impl From<String> for DIFKey {
36 fn from(s: String) -> Self {
37 DIFKey::Text(s)
38 }
39}
40impl From<&str> for DIFKey {
41 fn from(s: &str) -> Self {
42 DIFKey::Text(s.to_string())
43 }
44}
45impl From<i64> for DIFKey {
46 fn from(i: i64) -> Self {
47 DIFKey::Index(i)
48 }
49}
50impl From<DIFValueContainer> for DIFKey {
51 fn from(v: DIFValueContainer) -> Self {
52 DIFKey::Value(v)
53 }
54}
55
56#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
57pub struct DIFUpdate<'a> {
58 pub source_id: TransceiverId,
59 pub data: Cow<'a, DIFUpdateData>,
60}
61
62impl<'a> DIFUpdate<'a> {
63 pub fn new(source_id: TransceiverId, data: Cow<'a, DIFUpdateData>) -> Self {
65 DIFUpdate { source_id, data }
66 }
67}
68
69#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
74#[serde(tag = "kind", rename_all = "snake_case")]
75pub enum DIFUpdateData {
76 Replace { value: DIFValueContainer },
78
79 Set {
82 key: DIFKey,
83 value: DIFValueContainer,
84 },
85
86 Delete { key: DIFKey },
88
89 Clear,
91
92 Append { value: DIFValueContainer },
94
95 ListSplice {
97 start: u32,
98 delete_count: u32,
99 items: Vec<DIFValueContainer>,
100 },
101}
102
103impl DIFConvertible for DIFUpdateData {}
104
105impl DIFUpdateData {
106 pub fn replace(value: impl Into<DIFValueContainer>) -> Self {
108 DIFUpdateData::Replace {
109 value: value.into(),
110 }
111 }
112
113 pub fn set(
115 key: impl Into<DIFKey>,
116 value: impl Into<DIFValueContainer>,
117 ) -> Self {
118 DIFUpdateData::Set {
119 key: key.into(),
120 value: value.into(),
121 }
122 }
123
124 pub fn delete(key: impl Into<DIFKey>) -> Self {
126 DIFUpdateData::Delete { key: key.into() }
127 }
128
129 pub fn clear() -> Self {
131 DIFUpdateData::Clear
132 }
133
134 pub fn append(value: impl Into<DIFValueContainer>) -> Self {
136 DIFUpdateData::Append {
137 value: value.into(),
138 }
139 }
140
141 pub fn list_splice(
143 range: core::ops::Range<u32>,
144 items: Vec<DIFValueContainer>,
145 ) -> Self {
146 DIFUpdateData::ListSplice {
147 start: range.start,
148 delete_count: range.end - range.start,
149 items,
150 }
151 }
152
153 pub fn with_source(&self, source_id: TransceiverId) -> DIFUpdate<'_> {
154 DIFUpdate {
155 source_id,
156 data: Cow::Borrowed(self),
157 }
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use crate::dif::{representation::DIFValueRepresentation, value::DIFValue};
165
166 #[test]
167 fn serialize_replace() {
168 let dif_update =
169 DIFUpdateData::replace(DIFValueContainer::Value(DIFValue {
170 value: DIFValueRepresentation::String("Hello".to_string()),
171 ty: None,
172 }));
173 let serialized = dif_update.as_json();
174 assert_eq!(
175 serialized,
176 r#"{"kind":"replace","value":{"value":"Hello"}}"#
177 );
178 let deserialized = DIFUpdateData::from_json(&serialized);
179 assert_eq!(dif_update, deserialized);
180 }
181
182 #[test]
183 fn serialize_set() {
184 let dif_update = DIFUpdateData::set(
185 "name",
186 DIFValueContainer::Value(DIFValue {
187 value: DIFValueRepresentation::Number(42.0),
188 ty: None,
189 }),
190 );
191 let serialized = dif_update.as_json();
192 assert_eq!(
193 serialized,
194 r#"{"kind":"set","key":{"kind":"text","value":"name"},"value":{"value":42.0}}"#
195 );
196 let deserialized = DIFUpdateData::from_json(&serialized);
197 assert_eq!(dif_update, deserialized);
198 }
199
200 #[test]
201 fn serialize_remove() {
202 let dif_update = DIFUpdateData::delete("age");
203 let serialized = dif_update.as_json();
204 assert_eq!(
205 serialized,
206 r#"{"kind":"delete","key":{"kind":"text","value":"age"}}"#
207 );
208 let deserialized = DIFUpdateData::from_json(&serialized);
209 assert_eq!(dif_update, deserialized);
210 }
211
212 #[test]
213 fn serialize_clear() {
214 let dif_update = DIFUpdateData::clear();
215 let serialized = dif_update.as_json();
216 assert_eq!(serialized, r#"{"kind":"clear"}"#);
217 let deserialized = DIFUpdateData::from_json(&serialized);
218 assert_eq!(dif_update, deserialized);
219 }
220
221 #[test]
222 fn serialize_push() {
223 let dif_update =
224 DIFUpdateData::append(DIFValueContainer::Value(DIFValue {
225 value: DIFValueRepresentation::Boolean(true),
226 ty: None,
227 }));
228 let serialized = dif_update.as_json();
229 assert_eq!(serialized, r#"{"kind":"append","value":{"value":true}}"#);
230 let deserialized = DIFUpdateData::from_json(&serialized);
231 assert_eq!(dif_update, deserialized);
232 }
233}