1use crate::records::{
2 AdditionalTypeInfo, BinaryArray, BinaryType, ClassInfo, ClassWithId, ClassWithMembers,
3 ClassWithMembersAndTypes, MemberTypeInfo, ObjectValue, PrimitiveType, PrimitiveValue, Record,
4 SystemClassWithMembers, SystemClassWithMembersAndTypes,
5};
6use serde_json::{Map, Value, json};
7
8pub fn to_interleaved(records: &[Record]) -> Value {
9 let mut result = Vec::new();
10 for record in records {
11 if let Some(val) = record_to_value(record) {
12 result.push(val);
13 }
14 }
15 Value::Array(result)
16}
17
18fn record_to_value(record: &Record) -> Option<Value> {
19 match record {
20 Record::SerializationHeader(h) => Some(json!({
21 "$record": "SerializationHeader",
22 "root_id": h.root_id,
23 "header_id": h.header_id,
24 "major_version": h.major_version,
25 "minor_version": h.minor_version,
26 })),
27 Record::BinaryLibrary(l) => Some(json!({
28 "$record": "BinaryLibrary",
29 "library_id": l.library_id,
30 "library_name": l.library_name,
31 })),
32 Record::ClassWithMembersAndTypes(c) => {
33 let mut val = class_to_value(
34 &c.class_info.name,
35 c.class_info.object_id,
36 &c.class_info.member_names,
37 &c.member_values,
38 Some(c.library_id),
39 );
40 if let Value::Object(ref mut map) = val {
41 map.insert("$record".to_string(), json!("ClassWithMembersAndTypes"));
42 map.insert("$member_type_info".to_string(), json!(c.member_type_info));
43 }
44 Some(val)
45 }
46 Record::SystemClassWithMembersAndTypes(c) => {
47 let mut val = class_to_value(
48 &c.class_info.name,
49 c.class_info.object_id,
50 &c.class_info.member_names,
51 &c.member_values,
52 None,
53 );
54 if let Value::Object(ref mut map) = val {
55 map.insert(
56 "$record".to_string(),
57 json!("SystemClassWithMembersAndTypes"),
58 );
59 map.insert("$member_type_info".to_string(), json!(c.member_type_info));
60 }
61 Some(val)
62 }
63 Record::SystemClassWithMembers(c) => {
64 let mut val = class_to_value(
65 &c.class_info.name,
66 c.class_info.object_id,
67 &c.class_info.member_names,
68 &c.member_values,
69 None,
70 );
71 if let Value::Object(ref mut map) = val {
72 map.insert("$record".to_string(), json!("SystemClassWithMembers"));
73 }
74 Some(val)
75 }
76 Record::ClassWithMembers(c) => {
77 let mut val = class_to_value(
78 &c.class_info.name,
79 c.class_info.object_id,
80 &c.class_info.member_names,
81 &c.member_values,
82 Some(c.library_id),
83 );
84 if let Value::Object(ref mut map) = val {
85 map.insert("$record".to_string(), json!("ClassWithMembers"));
86 }
87 Some(val)
88 }
89 Record::ClassWithId(c) => Some(json!({
90 "$record": "ClassWithId",
91 "object_id": c.object_id,
92 "metadata_id": c.metadata_id,
93 "$values": c.member_values.iter().map(object_value_to_json).collect::<Vec<_>>(),
94 })),
95 Record::BinaryObjectString { object_id, value } => Some(json!({
96 "$record": "BinaryObjectString",
97 "object_id": *object_id,
98 "value": value,
99 })),
100 Record::BinaryArray(a) => Some(json!({
101 "$record": "BinaryArray",
102 "object_id": a.object_id,
103 "binary_array_type_enum": a.binary_array_type_enum,
104 "rank": a.rank,
105 "lengths": a.lengths,
106 "lower_bounds": a.lower_bounds,
107 "type_enum": a.type_enum,
108 "additional_type_info": a.additional_type_info,
109 "$values": a.element_values.iter().map(object_value_to_json).collect::<Vec<_>>(),
110 })),
111 Record::ArraySingleObject(a) => Some(json!({
112 "$record": "ArraySingleObject",
113 "object_id": a.object_id,
114 "length": a.length,
115 "$values": a.element_values.iter().map(object_value_to_json).collect::<Vec<_>>(),
116 })),
117 Record::ArraySinglePrimitive(a) => Some(json!({
118 "$record": "ArraySinglePrimitive",
119 "object_id": a.object_id,
120 "length": a.length,
121 "primitive_type_enum": a.primitive_type_enum,
122 "$values": a.element_values.iter().map(primitive_value_to_json).collect::<Vec<_>>(),
123 })),
124 Record::ArraySingleString(a) => Some(json!({
125 "$record": "ArraySingleString",
126 "object_id": a.object_id,
127 "length": a.length,
128 "$values": a.element_values.iter().map(object_value_to_json).collect::<Vec<_>>(),
129 })),
130 Record::MemberPrimitiveTyped {
131 primitive_type_enum,
132 value,
133 } => Some(json!({
134 "$record": "MemberPrimitiveTyped",
135 "primitive_type_enum": primitive_type_enum,
136 "value": primitive_value_to_json(value),
137 })),
138 Record::MemberReference { id_ref } => Some(json!({
139 "$record": "MemberReference",
140 "id_ref": *id_ref,
141 })),
142 Record::ObjectNull => Some(json!({ "$record": "ObjectNull" })),
143 Record::ObjectNullMultiple(n) => Some(json!({
144 "$record": "ObjectNullMultiple",
145 "null_count": n.null_count,
146 })),
147 Record::ObjectNullMultiple256(n) => Some(json!({
148 "$record": "ObjectNullMultiple256",
149 "null_count": n.null_count,
150 })),
151 Record::MessageEnd => Some(json!({ "$record": "MessageEnd" })),
152 }
153}
154
155fn class_to_value(
156 name: &str,
157 object_id: i32,
158 member_names: &[String],
159 member_values: &[ObjectValue],
160 library_id: Option<i32>,
161) -> Value {
162 let mut map = Map::new();
163 map.insert("$type".to_string(), Value::String(name.to_string()));
164 map.insert("$id".to_string(), json!(object_id));
165 if let Some(lib_id) = library_id {
166 map.insert("library_id".to_string(), json!(lib_id));
167 }
168
169 for (name, val) in member_names.iter().zip(member_values.iter()) {
170 map.insert(name.clone(), object_value_to_json(val));
171 }
172
173 Value::Object(map)
174}
175
176fn object_value_to_json(val: &ObjectValue) -> Value {
177 match val {
178 ObjectValue::Primitive(p) => primitive_value_to_json(p),
179 ObjectValue::Record(r) => record_to_value(r).unwrap_or(Value::Null),
180 }
181}
182
183fn primitive_value_to_json(val: &PrimitiveValue) -> Value {
184 match val {
185 PrimitiveValue::Boolean(b) => Value::Bool(*b),
186 PrimitiveValue::Byte(b) => json!(b),
187 PrimitiveValue::Char(c) => json!(c.to_string()),
188 PrimitiveValue::Decimal(s) => json!(s),
189 PrimitiveValue::Double(f) => json!(f),
190 PrimitiveValue::Int16(i) => json!(i),
191 PrimitiveValue::Int32(i) => json!(i),
192 PrimitiveValue::Int64(i) => json!(i),
193 PrimitiveValue::SByte(i) => json!(i),
194 PrimitiveValue::Single(f) => json!(f),
195 PrimitiveValue::TimeSpan(i) => json!(i),
196 PrimitiveValue::DateTime(u) => json!(u),
197 PrimitiveValue::UInt16(u) => json!(u),
198 PrimitiveValue::UInt32(u) => json!(u),
199 PrimitiveValue::UInt64(u) => json!(u),
200 PrimitiveValue::String(s) => Value::String(s.clone()),
201 PrimitiveValue::Null => Value::Null,
202 }
203}
204
205use std::collections::HashMap;
206
207pub fn from_interleaved(value: Value) -> Vec<Record> {
208 let mut deserializer = InterleavedDeserializer::new();
209 deserializer.deserialize(value)
210}
211
212struct InterleavedDeserializer {
213 metadata_registry: HashMap<i32, MemberTypeInfo>,
214}
215
216impl InterleavedDeserializer {
217 fn new() -> Self {
218 Self {
219 metadata_registry: HashMap::new(),
220 }
221 }
222
223 fn deserialize(&mut self, value: Value) -> Vec<Record> {
224 let mut records = Vec::new();
225 if let Value::Array(arr) = value {
226 for v in arr {
227 if let Some(record) = self.value_to_record(&v) {
228 records.push(record);
229 }
230 }
231 }
232 records
233 }
234
235 fn value_to_record(&mut self, v: &Value) -> Option<Record> {
236 let obj = v.as_object()?;
237 let record_type = obj.get("$record")?.as_str()?;
238
239 match record_type {
240 "SerializationHeader" => Some(Record::SerializationHeader(
241 serde_json::from_value(v.clone()).ok()?,
242 )),
243 "BinaryLibrary" => Some(Record::BinaryLibrary(
244 serde_json::from_value(v.clone()).ok()?,
245 )),
246 "ClassWithMembersAndTypes" => {
247 let class_info = self.value_to_class_info(v);
248 let member_type_info: MemberTypeInfo =
249 serde_json::from_value(obj.get("$member_type_info")?.clone()).ok()?;
250 let library_id = obj.get("library_id")?.as_i64()? as i32;
251
252 self.metadata_registry
253 .insert(class_info.object_id, member_type_info.clone());
254
255 let member_values = self.value_to_member_values_typed(
256 v,
257 &class_info.member_names,
258 &member_type_info,
259 );
260 Some(Record::ClassWithMembersAndTypes(ClassWithMembersAndTypes {
261 class_info,
262 member_type_info,
263 library_id,
264 member_values,
265 }))
266 }
267 "SystemClassWithMembersAndTypes" => {
268 let class_info = self.value_to_class_info(v);
269 let member_type_info: MemberTypeInfo =
270 serde_json::from_value(obj.get("$member_type_info")?.clone()).ok()?;
271
272 self.metadata_registry
273 .insert(class_info.object_id, member_type_info.clone());
274
275 let member_values = self.value_to_member_values_typed(
276 v,
277 &class_info.member_names,
278 &member_type_info,
279 );
280 Some(Record::SystemClassWithMembersAndTypes(
281 SystemClassWithMembersAndTypes {
282 class_info,
283 member_type_info,
284 member_values,
285 },
286 ))
287 }
288 "SystemClassWithMembers" => {
289 let class_info = self.value_to_class_info(v);
290 let member_values = self.value_to_member_values(v, &class_info.member_names);
291 Some(Record::SystemClassWithMembers(SystemClassWithMembers {
292 class_info,
293 member_values,
294 }))
295 }
296 "ClassWithMembers" => {
297 let class_info = self.value_to_class_info(v);
298 let library_id = obj.get("library_id")?.as_i64()? as i32;
299 let member_values = self.value_to_member_values(v, &class_info.member_names);
300 Some(Record::ClassWithMembers(ClassWithMembers {
301 class_info,
302 library_id,
303 member_values,
304 }))
305 }
306 "ClassWithId" => {
307 let object_id = obj.get("object_id")?.as_i64()? as i32;
308 let metadata_id = obj.get("metadata_id")?.as_i64()? as i32;
309 let member_values =
310 if let Some(mti) = self.metadata_registry.get(&metadata_id).cloned() {
311 let vals = obj.get("$values")?.as_array()?;
312 let mut result = Vec::new();
313 for (i, v) in vals.iter().enumerate() {
314 let bt = &mti.binary_type_enums[i];
315 let add_info = &mti.additional_infos[i];
316 match bt {
317 BinaryType::Primitive => {
318 if let AdditionalTypeInfo::Primitive(p_type) = add_info {
319 result.push(ObjectValue::Primitive(
320 self.json_to_primitive_value(v, p_type),
321 ));
322 } else {
323 result.push(self.json_to_object_value(v));
324 }
325 }
326 _ => result.push(self.json_to_object_value(v)),
327 }
328 }
329 result
330 } else {
331 obj.get("$values")?
332 .as_array()?
333 .iter()
334 .map(|v| self.json_to_object_value(v))
335 .collect()
336 };
337 Some(Record::ClassWithId(ClassWithId {
338 object_id,
339 metadata_id,
340 member_values,
341 }))
342 }
343 "BinaryObjectString" => Some(Record::BinaryObjectString {
344 object_id: obj.get("object_id")?.as_i64()? as i32,
345 value: obj.get("value")?.as_str()?.to_string(),
346 }),
347 "BinaryArray" => {
348 let type_enum: BinaryType =
349 serde_json::from_value(obj.get("type_enum")?.clone()).ok()?;
350 let additional_type_info: AdditionalTypeInfo =
351 serde_json::from_value(obj.get("additional_type_info")?.clone()).ok()?;
352 let element_values = obj
353 .get("$values")?
354 .as_array()?
355 .iter()
356 .map(|v| match type_enum {
357 BinaryType::Primitive => {
358 if let AdditionalTypeInfo::Primitive(p_type) = &additional_type_info {
359 ObjectValue::Primitive(self.json_to_primitive_value(v, p_type))
360 } else {
361 self.json_to_object_value(v)
362 }
363 }
364 _ => self.json_to_object_value(v),
365 })
366 .collect();
367 Some(Record::BinaryArray(BinaryArray {
368 object_id: obj.get("object_id")?.as_i64()? as i32,
369 binary_array_type_enum: obj.get("binary_array_type_enum")?.as_i64()? as u8,
370 rank: obj.get("rank")?.as_i64()? as i32,
371 lengths: serde_json::from_value(obj.get("lengths")?.clone()).ok()?,
372 lower_bounds: serde_json::from_value(obj.get("lower_bounds")?.clone()).ok()?,
373 type_enum,
374 additional_type_info,
375 element_values,
376 }))
377 }
378 "ArraySingleObject" => Some(Record::ArraySingleObject(
379 crate::records::ArraySingleObject {
380 object_id: obj.get("object_id")?.as_i64()? as i32,
381 length: obj.get("length")?.as_i64()? as i32,
382 element_values: obj
383 .get("$values")?
384 .as_array()?
385 .iter()
386 .map(|v| self.json_to_object_value(v))
387 .collect(),
388 },
389 )),
390 "ArraySinglePrimitive" => {
391 let primitive_type_enum: PrimitiveType =
392 serde_json::from_value(obj.get("primitive_type_enum")?.clone()).ok()?;
393 let element_values = obj
394 .get("$values")?
395 .as_array()?
396 .iter()
397 .map(
398 |v| match self.json_to_primitive_value(v, &primitive_type_enum) {
399 PrimitiveValue::Null => PrimitiveValue::Null,
400 p => p,
401 },
402 )
403 .collect();
404 Some(Record::ArraySinglePrimitive(
405 crate::records::ArraySinglePrimitive {
406 object_id: obj.get("object_id")?.as_i64()? as i32,
407 length: obj.get("length")?.as_i64()? as i32,
408 primitive_type_enum,
409 element_values,
410 },
411 ))
412 }
413 "ArraySingleString" => Some(Record::ArraySingleString(
414 crate::records::ArraySingleString {
415 object_id: obj.get("object_id")?.as_i64()? as i32,
416 length: obj.get("length")?.as_i64()? as i32,
417 element_values: obj
418 .get("$values")?
419 .as_array()?
420 .iter()
421 .map(|v| self.json_to_object_value(v))
422 .collect(),
423 },
424 )),
425 "MemberPrimitiveTyped" => {
426 let primitive_type_enum: PrimitiveType =
427 serde_json::from_value(obj.get("primitive_type_enum")?.clone()).ok()?;
428 let value = self.json_to_primitive_value(obj.get("value")?, &primitive_type_enum);
429 Some(Record::MemberPrimitiveTyped {
430 primitive_type_enum,
431 value,
432 })
433 }
434 "MemberReference" => Some(Record::MemberReference {
435 id_ref: obj.get("id_ref")?.as_i64()? as i32,
436 }),
437 "ObjectNull" => Some(Record::ObjectNull),
438 "ObjectNullMultiple" => Some(Record::ObjectNullMultiple(
439 crate::records::ObjectNullMultiple {
440 null_count: obj.get("null_count")?.as_i64()? as i32,
441 },
442 )),
443 "ObjectNullMultiple256" => Some(Record::ObjectNullMultiple256(
444 crate::records::ObjectNullMultiple256 {
445 null_count: obj.get("null_count")?.as_i64()? as u8,
446 },
447 )),
448 "MessageEnd" => Some(Record::MessageEnd),
449 _ => None,
450 }
451 }
452
453 fn value_to_class_info(&self, v: &Value) -> ClassInfo {
454 let obj = v.as_object().unwrap();
455 let name = obj.get("$type").unwrap().as_str().unwrap().to_string();
456 let object_id = obj.get("$id").unwrap().as_i64().unwrap() as i32;
457 let mut member_names = Vec::new();
458 for key in obj.keys() {
459 if !key.starts_with('$') && key != "library_id" {
460 member_names.push(key.clone());
461 }
462 }
463
464 ClassInfo {
465 object_id,
466 name,
467 member_count: member_names.len() as i32,
468 member_names,
469 }
470 }
471
472 fn value_to_member_values(&mut self, v: &Value, member_names: &[String]) -> Vec<ObjectValue> {
473 let obj = v.as_object().unwrap();
474 let mut values = Vec::new();
475 for name in member_names {
476 if let Some(val) = obj.get(name) {
477 values.push(self.json_to_object_value(val));
478 }
479 }
480 values
481 }
482
483 fn value_to_member_values_typed(
484 &mut self,
485 v: &Value,
486 member_names: &[String],
487 member_type_info: &MemberTypeInfo,
488 ) -> Vec<ObjectValue> {
489 let obj = v.as_object().unwrap();
490 let mut values = Vec::new();
491 for (i, name) in member_names.iter().enumerate() {
492 if let Some(val) = obj.get(name) {
493 let binary_type = &member_type_info.binary_type_enums[i];
494 let additional_info = &member_type_info.additional_infos[i];
495
496 match binary_type {
497 BinaryType::Primitive => {
498 if let AdditionalTypeInfo::Primitive(p_type) = additional_info {
499 values.push(ObjectValue::Primitive(
500 self.json_to_primitive_value(val, p_type),
501 ));
502 } else {
503 values.push(self.json_to_object_value(val));
504 }
505 }
506 _ => {
507 values.push(self.json_to_object_value(val));
508 }
509 }
510 }
511 }
512 values
513 }
514
515 fn json_to_primitive_value(&self, v: &Value, t: &PrimitiveType) -> PrimitiveValue {
516 match t {
517 PrimitiveType::Boolean => PrimitiveValue::Boolean(v.as_bool().unwrap_or(false)),
518 PrimitiveType::Byte => PrimitiveValue::Byte(v.as_i64().unwrap_or(0) as u8),
519 PrimitiveType::UInt16 => PrimitiveValue::UInt16(v.as_u64().unwrap_or(0) as u16),
520 PrimitiveType::UInt32 => PrimitiveValue::UInt32(v.as_u64().unwrap_or(0) as u32),
521 PrimitiveType::Char => {
522 PrimitiveValue::Char(v.as_str().and_then(|s| s.chars().next()).unwrap_or('\0'))
523 }
524 PrimitiveType::Decimal => {
525 PrimitiveValue::Decimal(v.as_str().unwrap_or("0").to_string())
526 }
527 PrimitiveType::Double => PrimitiveValue::Double(v.as_f64().unwrap_or(0.0)),
528 PrimitiveType::Int16 => PrimitiveValue::Int16(v.as_i64().unwrap_or(0) as i16),
529 PrimitiveType::Int32 => PrimitiveValue::Int32(v.as_i64().unwrap_or(0) as i32),
530 PrimitiveType::Int64 => PrimitiveValue::Int64(v.as_i64().unwrap_or(0)),
531 PrimitiveType::SByte => PrimitiveValue::SByte(v.as_i64().unwrap_or(0) as i8),
532 PrimitiveType::Single => PrimitiveValue::Single(v.as_f64().unwrap_or(0.0) as f32),
533 PrimitiveType::TimeSpan => PrimitiveValue::TimeSpan(v.as_i64().unwrap_or(0)),
534 PrimitiveType::DateTime => PrimitiveValue::DateTime(
535 v.as_u64()
536 .or_else(|| v.as_i64().map(|i| i as u64))
537 .unwrap_or(0),
538 ),
539 PrimitiveType::UInt64 => PrimitiveValue::UInt64(
540 v.as_u64()
541 .or_else(|| v.as_i64().map(|i| i as u64))
542 .unwrap_or(0),
543 ),
544 PrimitiveType::String => PrimitiveValue::String(v.as_str().unwrap_or("").to_string()),
545 PrimitiveType::Null => PrimitiveValue::Null,
546 }
547 }
548
549 fn json_to_object_value(&mut self, v: &Value) -> ObjectValue {
550 if let Some(record) = self.value_to_record(v) {
551 return ObjectValue::Record(Box::new(record));
552 }
553
554 if v.is_boolean() {
556 ObjectValue::Primitive(PrimitiveValue::Boolean(v.as_bool().unwrap()))
557 } else if v.is_number() {
558 if v.is_i64() {
559 ObjectValue::Primitive(PrimitiveValue::Int32(v.as_i64().unwrap() as i32))
560 } else if v.is_u64() {
561 ObjectValue::Primitive(PrimitiveValue::UInt32(v.as_u64().unwrap() as u32))
562 } else {
563 ObjectValue::Primitive(PrimitiveValue::Double(v.as_f64().unwrap()))
564 }
565 } else if v.is_string() {
566 ObjectValue::Primitive(PrimitiveValue::String(v.as_str().unwrap().to_string()))
567 } else {
568 ObjectValue::Primitive(PrimitiveValue::Null)
569 }
570 }
571}