1use crate::Value;
29use smallvec::SmallVec;
30use std::collections::BTreeMap;
31
32#[derive(Debug, Clone, PartialEq)]
43pub struct Node {
44 pub type_name: String,
47 pub id: String,
49 pub fields: SmallVec<[Value; 4]>,
52 pub children: Option<Box<BTreeMap<String, Vec<Node>>>>,
55 pub child_count: u16,
58}
59
60impl Default for Node {
61 fn default() -> Self {
62 Self {
63 type_name: String::new(),
64 id: String::new(),
65 fields: SmallVec::new(),
66 children: None,
67 child_count: 0,
68 }
69 }
70}
71
72impl Node {
73 pub fn new(type_name: impl Into<String>, id: impl Into<String>, fields: Vec<Value>) -> Self {
75 Self {
76 type_name: type_name.into(),
77 id: id.into(),
78 fields: SmallVec::from_vec(fields),
79 children: None,
80 child_count: 0,
81 }
82 }
83
84 pub fn get_field(&self, index: usize) -> Option<&Value> {
86 self.fields.get(index)
87 }
88
89 pub fn add_child(&mut self, child_type: impl Into<String>, child: Node) {
92 let children = self
93 .children
94 .get_or_insert_with(|| Box::new(BTreeMap::new()));
95 children.entry(child_type.into()).or_default().push(child);
96 }
97
98 pub fn set_child_count(&mut self, count: usize) {
101 self.child_count = count.min(u16::MAX as usize) as u16;
102 }
103
104 pub fn get_child_count(&self) -> Option<usize> {
106 if self.child_count > 0 {
107 Some(self.child_count as usize)
108 } else {
109 None
110 }
111 }
112
113 pub fn with_child_count(
120 type_name: impl Into<String>,
121 id: impl Into<String>,
122 fields: Vec<Value>,
123 child_count: usize,
124 ) -> Self {
125 Self {
126 type_name: type_name.into(),
127 id: id.into(),
128 fields: SmallVec::from_vec(fields),
129 children: None,
130 child_count: child_count.min(u16::MAX as usize) as u16,
131 }
132 }
133
134 pub fn children(&self) -> Option<&BTreeMap<String, Vec<Node>>> {
136 self.children.as_deref()
137 }
138
139 pub fn children_mut(&mut self) -> Option<&mut BTreeMap<String, Vec<Node>>> {
141 self.children.as_deref_mut()
142 }
143}
144
145#[derive(Debug, Clone, PartialEq)]
147pub struct MatrixList {
148 pub type_name: String,
150 pub schema: Vec<String>,
152 pub rows: Vec<Node>,
154 pub count_hint: Option<usize>,
156}
157
158impl MatrixList {
159 pub fn new(type_name: impl Into<String>, schema: Vec<String>) -> Self {
161 Self {
162 type_name: type_name.into(),
163 schema,
164 rows: Vec::new(),
165 count_hint: None,
166 }
167 }
168
169 pub fn with_rows(type_name: impl Into<String>, schema: Vec<String>, rows: Vec<Node>) -> Self {
171 Self {
172 type_name: type_name.into(),
173 schema,
174 rows,
175 count_hint: None,
176 }
177 }
178
179 pub fn with_count_hint(
181 type_name: impl Into<String>,
182 schema: Vec<String>,
183 count_hint: usize,
184 ) -> Self {
185 Self {
186 type_name: type_name.into(),
187 schema,
188 rows: Vec::new(),
189 count_hint: Some(count_hint),
190 }
191 }
192
193 pub fn add_row(&mut self, node: Node) {
195 self.rows.push(node);
196 }
197
198 pub fn column_count(&self) -> usize {
200 self.schema.len()
201 }
202}
203
204#[derive(Debug, Clone, PartialEq)]
206pub enum Item {
207 Scalar(Value),
209 Object(BTreeMap<String, Item>),
211 List(MatrixList),
213}
214
215impl Item {
216 pub fn as_scalar(&self) -> Option<&Value> {
218 match self {
219 Self::Scalar(v) => Some(v),
220 _ => None,
221 }
222 }
223
224 pub fn as_object(&self) -> Option<&BTreeMap<String, Item>> {
226 match self {
227 Self::Object(o) => Some(o),
228 _ => None,
229 }
230 }
231
232 pub fn as_list(&self) -> Option<&MatrixList> {
234 match self {
235 Self::List(l) => Some(l),
236 _ => None,
237 }
238 }
239}
240
241#[derive(Debug, Clone, PartialEq)]
243pub struct Document {
244 pub version: (u32, u32),
246 pub schema_versions: BTreeMap<String, crate::schema_version::SchemaVersion>,
249 pub aliases: BTreeMap<String, String>,
251 pub structs: BTreeMap<String, Vec<String>>,
253 pub nests: BTreeMap<String, Vec<String>>,
256 pub root: BTreeMap<String, Item>,
258}
259
260impl Document {
261 pub fn new(version: (u32, u32)) -> Self {
263 Self {
264 version,
265 schema_versions: BTreeMap::new(),
266 aliases: BTreeMap::new(),
267 structs: BTreeMap::new(),
268 nests: BTreeMap::new(),
269 root: BTreeMap::new(),
270 }
271 }
272
273 pub fn get_schema_version(
275 &self,
276 type_name: &str,
277 ) -> Option<crate::schema_version::SchemaVersion> {
278 self.schema_versions.get(type_name).copied()
279 }
280
281 pub fn set_schema_version(
283 &mut self,
284 type_name: String,
285 version: crate::schema_version::SchemaVersion,
286 ) {
287 self.schema_versions.insert(type_name, version);
288 }
289
290 pub fn get(&self, key: &str) -> Option<&Item> {
292 self.root.get(key)
293 }
294
295 pub fn get_schema(&self, type_name: &str) -> Option<&Vec<String>> {
297 self.structs.get(type_name)
298 }
299
300 pub fn get_child_types(&self, parent_type: &str) -> Option<&Vec<String>> {
303 self.nests.get(parent_type)
304 }
305
306 pub fn expand_alias(&self, key: &str) -> Option<&String> {
308 self.aliases.get(key)
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315
316 #[test]
319 fn test_node_new() {
320 let node = Node::new("User", "user-1", vec![Value::Int(42)]);
321 assert_eq!(node.type_name, "User");
322 assert_eq!(node.id, "user-1");
323 assert_eq!(node.fields.len(), 1);
324 assert!(node.children.is_none());
325 }
326
327 #[test]
328 fn test_node_get_field() {
329 let node = Node::new(
330 "User",
331 "1",
332 vec![Value::Int(1), Value::String("name".to_string().into())],
333 );
334 assert_eq!(node.get_field(0), Some(&Value::Int(1)));
335 assert_eq!(
336 node.get_field(1),
337 Some(&Value::String("name".to_string().into()))
338 );
339 assert_eq!(node.get_field(2), None);
340 }
341
342 #[test]
343 fn test_node_add_child() {
344 let mut parent = Node::new("User", "1", vec![]);
345 let child = Node::new("Post", "p1", vec![]);
346 parent.add_child("Post", child);
347
348 let children = parent.children().unwrap();
349 assert!(children.contains_key("Post"));
350 assert_eq!(children["Post"].len(), 1);
351 }
352
353 #[test]
354 fn test_node_add_multiple_children_same_type() {
355 let mut parent = Node::new("User", "1", vec![]);
356 parent.add_child("Post", Node::new("Post", "p1", vec![]));
357 parent.add_child("Post", Node::new("Post", "p2", vec![]));
358
359 let children = parent.children().unwrap();
360 assert_eq!(children["Post"].len(), 2);
361 }
362
363 #[test]
364 fn test_node_add_children_different_types() {
365 let mut parent = Node::new("User", "1", vec![]);
366 parent.add_child("Post", Node::new("Post", "p1", vec![]));
367 parent.add_child("Comment", Node::new("Comment", "c1", vec![]));
368
369 let children = parent.children().unwrap();
370 assert_eq!(children.len(), 2);
371 assert!(children.contains_key("Post"));
372 assert!(children.contains_key("Comment"));
373 }
374
375 #[test]
376 fn test_node_equality() {
377 let a = Node::new("User", "1", vec![Value::Int(42)]);
378 let b = Node::new("User", "1", vec![Value::Int(42)]);
379 assert_eq!(a, b);
380 }
381
382 #[test]
383 fn test_node_clone() {
384 let mut original = Node::new("User", "1", vec![Value::Int(42)]);
385 original.add_child("Post", Node::new("Post", "p1", vec![]));
386 let cloned = original.clone();
387 assert_eq!(original, cloned);
388 }
389
390 #[test]
391 fn test_node_debug() {
392 let node = Node::new("User", "1", vec![]);
393 let debug = format!("{:?}", node);
394 assert!(debug.contains("User"));
395 assert!(debug.contains("type_name"));
396 }
397
398 #[test]
399 fn test_node_child_count() {
400 let node = Node::with_child_count("User", "1", vec![], 5);
401 assert_eq!(node.get_child_count(), Some(5));
402 }
403
404 #[test]
405 fn test_node_no_child_count() {
406 let node = Node::new("User", "1", vec![]);
407 assert_eq!(node.get_child_count(), None);
408 }
409
410 #[test]
411 fn test_node_set_child_count() {
412 let mut node = Node::new("User", "1", vec![]);
413 node.set_child_count(10);
414 assert_eq!(node.get_child_count(), Some(10));
415 }
416
417 #[test]
418 fn test_node_child_count_saturation() {
419 let node = Node::with_child_count("User", "1", vec![], 100_000);
420 assert_eq!(node.get_child_count(), Some(65535)); }
422
423 #[test]
424 fn test_node_lazy_children() {
425 let node = Node::new("User", "1", vec![]);
426 assert!(node.children.is_none()); }
428
429 #[test]
430 fn test_node_children_accessor() {
431 let mut node = Node::new("User", "1", vec![]);
432 assert!(node.children().is_none());
433
434 node.add_child("Post", Node::new("Post", "p1", vec![]));
435 assert!(node.children().is_some());
436 assert!(node.children().unwrap().contains_key("Post"));
437 }
438
439 #[test]
440 fn test_node_children_mut_accessor() {
441 let mut node = Node::new("User", "1", vec![]);
442 node.add_child("Post", Node::new("Post", "p1", vec![]));
443
444 if let Some(children) = node.children_mut() {
445 children.insert("Comment".to_string(), vec![]);
446 }
447
448 assert!(node.children().unwrap().contains_key("Comment"));
449 }
450
451 #[test]
454 fn test_matrix_list_new() {
455 let list = MatrixList::new("User", vec!["id".to_string(), "name".to_string()]);
456 assert_eq!(list.type_name, "User");
457 assert_eq!(list.schema, vec!["id", "name"]);
458 assert!(list.rows.is_empty());
459 }
460
461 #[test]
462 fn test_matrix_list_add_row() {
463 let mut list = MatrixList::new("User", vec!["id".to_string()]);
464 list.add_row(Node::new("User", "1", vec![]));
465 assert_eq!(list.rows.len(), 1);
466 }
467
468 #[test]
469 fn test_matrix_list_column_count() {
470 let list = MatrixList::new(
471 "User",
472 vec!["a".to_string(), "b".to_string(), "c".to_string()],
473 );
474 assert_eq!(list.column_count(), 3);
475 }
476
477 #[test]
478 fn test_matrix_list_empty_schema() {
479 let list = MatrixList::new("Empty", vec![]);
480 assert_eq!(list.column_count(), 0);
481 }
482
483 #[test]
484 fn test_matrix_list_equality() {
485 let mut a = MatrixList::new("User", vec!["id".to_string()]);
486 a.add_row(Node::new("User", "1", vec![]));
487 let mut b = MatrixList::new("User", vec!["id".to_string()]);
488 b.add_row(Node::new("User", "1", vec![]));
489 assert_eq!(a, b);
490 }
491
492 #[test]
493 fn test_matrix_list_clone() {
494 let mut list = MatrixList::new("User", vec!["id".to_string()]);
495 list.add_row(Node::new("User", "1", vec![]));
496 let cloned = list.clone();
497 assert_eq!(list, cloned);
498 }
499
500 #[test]
501 fn test_matrix_list_with_rows() {
502 let rows = vec![
503 Node::new("User", "1", vec![]),
504 Node::new("User", "2", vec![]),
505 ];
506 let list = MatrixList::with_rows("User", vec!["id".to_string()], rows);
507 assert_eq!(list.rows.len(), 2);
508 }
509
510 #[test]
511 fn test_matrix_list_with_count_hint() {
512 let list = MatrixList::with_count_hint("User", vec!["id".to_string()], 100);
513 assert_eq!(list.count_hint, Some(100));
514 }
515
516 #[test]
519 fn test_item_scalar() {
520 let item = Item::Scalar(Value::Int(42));
521 assert!(item.as_scalar().is_some());
522 assert!(item.as_object().is_none());
523 assert!(item.as_list().is_none());
524 }
525
526 #[test]
527 fn test_item_object() {
528 let mut obj = BTreeMap::new();
529 obj.insert("key".to_string(), Item::Scalar(Value::Int(1)));
530 let item = Item::Object(obj);
531 assert!(item.as_object().is_some());
532 assert!(item.as_scalar().is_none());
533 }
534
535 #[test]
536 fn test_item_list() {
537 let list = MatrixList::new("User", vec!["id".to_string()]);
538 let item = Item::List(list);
539 assert!(item.as_list().is_some());
540 assert!(item.as_scalar().is_none());
541 }
542
543 #[test]
544 fn test_item_as_scalar_returns_value() {
545 let item = Item::Scalar(Value::String("hello".to_string().into()));
546 let value = item.as_scalar().unwrap();
547 assert_eq!(value.as_str(), Some("hello"));
548 }
549
550 #[test]
551 fn test_item_as_object_returns_map() {
552 let mut obj = BTreeMap::new();
553 obj.insert("a".to_string(), Item::Scalar(Value::Int(1)));
554 let item = Item::Object(obj);
555 let map = item.as_object().unwrap();
556 assert!(map.contains_key("a"));
557 }
558
559 #[test]
560 fn test_item_equality() {
561 let a = Item::Scalar(Value::Int(42));
562 let b = Item::Scalar(Value::Int(42));
563 assert_eq!(a, b);
564 }
565
566 #[test]
567 fn test_item_clone() {
568 let item = Item::Scalar(Value::String("test".to_string().into()));
569 let cloned = item.clone();
570 assert_eq!(item, cloned);
571 }
572
573 #[test]
576 fn test_document_new() {
577 let doc = Document::new((2, 0));
578 assert_eq!(doc.version, (2, 0));
579 assert!(doc.aliases.is_empty());
580 assert!(doc.structs.is_empty());
581 assert!(doc.nests.is_empty());
582 assert!(doc.root.is_empty());
583 }
584
585 #[test]
586 fn test_document_get() {
587 let mut doc = Document::new((2, 0));
588 doc.root
589 .insert("key".to_string(), Item::Scalar(Value::Int(42)));
590 assert!(doc.get("key").is_some());
591 assert!(doc.get("missing").is_none());
592 }
593
594 #[test]
595 fn test_document_get_schema() {
596 let mut doc = Document::new((2, 0));
597 doc.structs.insert(
598 "User".to_string(),
599 vec!["id".to_string(), "name".to_string()],
600 );
601 let schema = doc.get_schema("User").unwrap();
602 assert_eq!(schema, &vec!["id".to_string(), "name".to_string()]);
603 assert!(doc.get_schema("Missing").is_none());
604 }
605
606 #[test]
607 fn test_document_get_child_types() {
608 let mut doc = Document::new((2, 0));
609 doc.nests
610 .insert("User".to_string(), vec!["Post".to_string()]);
611 assert_eq!(doc.get_child_types("User"), Some(&vec!["Post".to_string()]));
612 assert!(doc.get_child_types("Post").is_none());
613 }
614
615 #[test]
616 fn test_document_expand_alias() {
617 let mut doc = Document::new((2, 0));
618 doc.aliases.insert("active".to_string(), "true".to_string());
619 assert_eq!(doc.expand_alias("active"), Some(&"true".to_string()));
620 assert!(doc.expand_alias("missing").is_none());
621 }
622
623 #[test]
624 fn test_document_equality() {
625 let a = Document::new((2, 0));
626 let b = Document::new((2, 0));
627 assert_eq!(a, b);
628 }
629
630 #[test]
631 fn test_document_clone() {
632 let mut doc = Document::new((2, 0));
633 doc.aliases.insert("key".to_string(), "value".to_string());
634 let cloned = doc.clone();
635 assert_eq!(doc, cloned);
636 }
637
638 #[test]
639 fn test_document_debug() {
640 let doc = Document::new((2, 0));
641 let debug = format!("{:?}", doc);
642 assert!(debug.contains("version"));
643 assert!(debug.contains("aliases"));
644 }
645
646 #[test]
649 fn test_node_empty_fields() {
650 let node = Node::new("Type", "id", vec![]);
651 assert!(node.fields.is_empty());
652 assert!(node.get_field(0).is_none());
653 }
654
655 #[test]
656 fn test_node_unicode_id() {
657 let node = Node::new("User", "日本語", vec![]);
658 assert_eq!(node.id, "日本語");
659 }
660
661 #[test]
662 fn test_document_version_zero() {
663 let doc = Document::new((0, 0));
664 assert_eq!(doc.version, (0, 0));
665 }
666
667 #[test]
668 fn test_document_large_version() {
669 let doc = Document::new((999, 999));
670 assert_eq!(doc.version, (999, 999));
671 }
672
673 #[test]
674 fn test_nested_items() {
675 let mut inner = BTreeMap::new();
676 inner.insert("nested".to_string(), Item::Scalar(Value::Int(42)));
677
678 let mut outer = BTreeMap::new();
679 outer.insert("inner".to_string(), Item::Object(inner));
680
681 let item = Item::Object(outer);
682 let obj = item.as_object().unwrap();
683 let inner_item = obj.get("inner").unwrap();
684 let inner_obj = inner_item.as_object().unwrap();
685 assert!(inner_obj.contains_key("nested"));
686 }
687
688 #[test]
689 fn test_deeply_nested_nodes() {
690 let mut root = Node::new("A", "a", vec![]);
691 let mut child = Node::new("B", "b", vec![]);
692 child.add_child("C", Node::new("C", "c", vec![]));
693 root.add_child("B", child);
694
695 let children = root.children().unwrap();
696 assert_eq!(children["B"].len(), 1);
697 let b_children = children["B"][0].children().unwrap();
698 assert_eq!(b_children["C"].len(), 1);
699 }
700
701 #[test]
702 fn test_node_default() {
703 let node = Node::default();
704 assert_eq!(node.type_name, "");
705 assert!(node.fields.is_empty());
706 assert!(node.children.is_none());
707 assert_eq!(node.child_count, 0);
708 }
709
710 #[test]
713 fn test_document_schema_versions_empty() {
714 let doc = Document::new((2, 0));
715 assert!(doc.schema_versions.is_empty());
716 }
717
718 #[test]
719 fn test_document_set_schema_version() {
720 use crate::schema_version::SchemaVersion;
721 let mut doc = Document::new((2, 0));
722 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 2, 3));
723 assert_eq!(doc.schema_versions.len(), 1);
724 assert!(doc.schema_versions.contains_key("User"));
725 }
726
727 #[test]
728 fn test_document_get_schema_version() {
729 use crate::schema_version::SchemaVersion;
730 let mut doc = Document::new((2, 0));
731 let version = SchemaVersion::new(2, 0, 0);
732 doc.set_schema_version("Post".to_string(), version);
733 assert_eq!(doc.get_schema_version("Post"), Some(version));
734 assert_eq!(doc.get_schema_version("User"), None);
735 }
736
737 #[test]
738 fn test_document_multiple_schema_versions() {
739 use crate::schema_version::SchemaVersion;
740 let mut doc = Document::new((2, 0));
741 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
742 doc.set_schema_version("Post".to_string(), SchemaVersion::new(2, 1, 0));
743 doc.set_schema_version("Comment".to_string(), SchemaVersion::new(1, 5, 2));
744
745 assert_eq!(doc.schema_versions.len(), 3);
746 assert_eq!(
747 doc.get_schema_version("User"),
748 Some(SchemaVersion::new(1, 0, 0))
749 );
750 assert_eq!(
751 doc.get_schema_version("Post"),
752 Some(SchemaVersion::new(2, 1, 0))
753 );
754 assert_eq!(
755 doc.get_schema_version("Comment"),
756 Some(SchemaVersion::new(1, 5, 2))
757 );
758 }
759
760 #[test]
761 fn test_document_replace_schema_version() {
762 use crate::schema_version::SchemaVersion;
763 let mut doc = Document::new((2, 0));
764 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
765 doc.set_schema_version("User".to_string(), SchemaVersion::new(2, 0, 0));
766
767 assert_eq!(doc.schema_versions.len(), 1);
768 assert_eq!(
769 doc.get_schema_version("User"),
770 Some(SchemaVersion::new(2, 0, 0))
771 );
772 }
773
774 #[test]
775 fn test_document_schema_version_with_clone() {
776 use crate::schema_version::SchemaVersion;
777 let mut doc = Document::new((2, 0));
778 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
779 let cloned = doc.clone();
780
781 assert_eq!(cloned.schema_versions.len(), 1);
782 assert_eq!(
783 cloned.get_schema_version("User"),
784 Some(SchemaVersion::new(1, 0, 0))
785 );
786 }
787
788 #[test]
789 fn test_document_schema_version_equality() {
790 use crate::schema_version::SchemaVersion;
791 let mut a = Document::new((2, 0));
792 a.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
793
794 let mut b = Document::new((2, 0));
795 b.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
796
797 assert_eq!(a, b);
798 }
799
800 #[test]
801 fn test_document_schema_version_inequality() {
802 use crate::schema_version::SchemaVersion;
803 let mut a = Document::new((2, 0));
804 a.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
805
806 let mut b = Document::new((2, 0));
807 b.set_schema_version("User".to_string(), SchemaVersion::new(2, 0, 0));
808
809 assert_ne!(a, b);
810 }
811}