1use serde::{Deserialize, Serialize};
18use std::ops::{Deref, DerefMut};
19
20pub(crate) const DEFAULT_VERSION_KEY: &str = "version";
22
23pub(crate) const DEFAULT_DATA_KEY: &str = "data";
25
26#[derive(Debug, Clone)]
31pub struct ForwardContext {
32 pub(crate) original_version: String,
34 pub(crate) unknown_fields: serde_json::Map<String, serde_json::Value>,
36 pub(crate) was_lossy: bool,
38 pub(crate) version_key: String,
40 pub(crate) data_key: String,
42 pub(crate) was_flat: bool,
44}
45
46impl ForwardContext {
47 pub(crate) fn new(
49 original_version: String,
50 unknown_fields: serde_json::Map<String, serde_json::Value>,
51 was_lossy: bool,
52 version_key: String,
53 data_key: String,
54 was_flat: bool,
55 ) -> Self {
56 Self {
57 original_version,
58 unknown_fields,
59 was_lossy,
60 version_key,
61 data_key,
62 was_flat,
63 }
64 }
65
66 pub fn original_version(&self) -> &str {
68 &self.original_version
69 }
70
71 pub fn was_lossy(&self) -> bool {
73 self.was_lossy
74 }
75
76 pub fn unknown_fields(&self) -> &serde_json::Map<String, serde_json::Value> {
78 &self.unknown_fields
79 }
80}
81
82#[derive(Debug, Clone)]
105pub struct Forwardable<T> {
106 pub inner: T,
108 ctx: ForwardContext,
110}
111
112impl<T> Forwardable<T> {
113 pub(crate) fn new(inner: T, ctx: ForwardContext) -> Self {
115 Self { inner, ctx }
116 }
117
118 pub fn original_version(&self) -> &str {
120 self.ctx.original_version()
121 }
122
123 pub fn was_lossy(&self) -> bool {
125 self.ctx.was_lossy()
126 }
127
128 pub fn unknown_fields(&self) -> &serde_json::Map<String, serde_json::Value> {
130 self.ctx.unknown_fields()
131 }
132
133 pub fn context(&self) -> &ForwardContext {
135 &self.ctx
136 }
137
138 pub fn into_inner(self) -> T {
140 self.inner
141 }
142}
143
144impl<T> Deref for Forwardable<T> {
145 type Target = T;
146
147 fn deref(&self) -> &Self::Target {
148 &self.inner
149 }
150}
151
152impl<T> DerefMut for Forwardable<T> {
153 fn deref_mut(&mut self) -> &mut Self::Target {
154 &mut self.inner
155 }
156}
157
158impl<T: Serialize> Serialize for Forwardable<T> {
159 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160 where
161 S: serde::Serializer,
162 {
163 self.inner.serialize(serializer)
166 }
167}
168
169impl<'de, T: Deserialize<'de>> Deserialize<'de> for Forwardable<T> {
170 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171 where
172 D: serde::Deserializer<'de>,
173 {
174 let inner = T::deserialize(deserializer)?;
177 Ok(Self {
178 inner,
179 ctx: ForwardContext::new(
180 String::new(),
181 serde_json::Map::new(),
182 false,
183 DEFAULT_VERSION_KEY.to_string(),
184 DEFAULT_DATA_KEY.to_string(),
185 false,
186 ),
187 })
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
196 struct TestEntity {
197 id: String,
198 name: String,
199 }
200
201 #[test]
202 fn test_forwardable_deref() {
203 let entity = TestEntity {
204 id: "1".to_string(),
205 name: "test".to_string(),
206 };
207 let ctx = ForwardContext::new(
208 "2.0.0".to_string(),
209 serde_json::Map::new(),
210 true,
211 "version".to_string(),
212 "data".to_string(),
213 false,
214 );
215 let forwardable = Forwardable::new(entity, ctx);
216
217 assert_eq!(forwardable.id, "1");
219 assert_eq!(forwardable.name, "test");
220 }
221
222 #[test]
223 fn test_forwardable_deref_mut() {
224 let entity = TestEntity {
225 id: "1".to_string(),
226 name: "test".to_string(),
227 };
228 let ctx = ForwardContext::new(
229 "2.0.0".to_string(),
230 serde_json::Map::new(),
231 true,
232 "version".to_string(),
233 "data".to_string(),
234 false,
235 );
236 let mut forwardable = Forwardable::new(entity, ctx);
237
238 forwardable.name = "updated".to_string();
240 assert_eq!(forwardable.name, "updated");
241 }
242
243 #[test]
244 fn test_forwardable_context_access() {
245 let mut unknown = serde_json::Map::new();
246 unknown.insert(
247 "new_field".to_string(),
248 serde_json::Value::String("value".to_string()),
249 );
250
251 let entity = TestEntity {
252 id: "1".to_string(),
253 name: "test".to_string(),
254 };
255 let ctx = ForwardContext::new(
256 "2.0.0".to_string(),
257 unknown,
258 true,
259 "version".to_string(),
260 "data".to_string(),
261 false,
262 );
263 let forwardable = Forwardable::new(entity, ctx);
264
265 assert_eq!(forwardable.original_version(), "2.0.0");
266 assert!(forwardable.was_lossy());
267 assert_eq!(forwardable.unknown_fields().len(), 1);
268 assert!(forwardable.unknown_fields().contains_key("new_field"));
269 }
270
271 #[test]
272 fn test_forwardable_into_inner() {
273 let entity = TestEntity {
274 id: "1".to_string(),
275 name: "test".to_string(),
276 };
277 let ctx = ForwardContext::new(
278 "1.0.0".to_string(),
279 serde_json::Map::new(),
280 false,
281 "version".to_string(),
282 "data".to_string(),
283 false,
284 );
285 let forwardable = Forwardable::new(entity.clone(), ctx);
286
287 let inner = forwardable.into_inner();
288 assert_eq!(inner, entity);
289 }
290
291 #[test]
292 fn test_forwardable_serialize() {
293 let entity = TestEntity {
294 id: "1".to_string(),
295 name: "test".to_string(),
296 };
297 let ctx = ForwardContext::new(
298 "2.0.0".to_string(),
299 serde_json::Map::new(),
300 true,
301 "version".to_string(),
302 "data".to_string(),
303 false,
304 );
305 let forwardable = Forwardable::new(entity, ctx);
306
307 let json = serde_json::to_string(&forwardable).unwrap();
309 assert!(json.contains("\"id\":\"1\""));
310 assert!(json.contains("\"name\":\"test\""));
311 }
312
313 #[test]
314 fn test_forwardable_deserialize() {
315 let json = r#"{"id":"1","name":"test"}"#;
317 let forwardable: Forwardable<TestEntity> = serde_json::from_str(json).unwrap();
318
319 assert_eq!(forwardable.id, "1");
320 assert_eq!(forwardable.name, "test");
321 assert_eq!(forwardable.original_version(), "");
323 assert!(!forwardable.was_lossy());
324 }
325}