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, String>,
255 pub root: BTreeMap<String, Item>,
257}
258
259impl Document {
260 pub fn new(version: (u32, u32)) -> Self {
262 Self {
263 version,
264 schema_versions: BTreeMap::new(),
265 aliases: BTreeMap::new(),
266 structs: BTreeMap::new(),
267 nests: BTreeMap::new(),
268 root: BTreeMap::new(),
269 }
270 }
271
272 pub fn get_schema_version(
274 &self,
275 type_name: &str,
276 ) -> Option<crate::schema_version::SchemaVersion> {
277 self.schema_versions.get(type_name).copied()
278 }
279
280 pub fn set_schema_version(
282 &mut self,
283 type_name: String,
284 version: crate::schema_version::SchemaVersion,
285 ) {
286 self.schema_versions.insert(type_name, version);
287 }
288
289 pub fn get(&self, key: &str) -> Option<&Item> {
291 self.root.get(key)
292 }
293
294 pub fn get_schema(&self, type_name: &str) -> Option<&Vec<String>> {
296 self.structs.get(type_name)
297 }
298
299 pub fn get_child_type(&self, parent_type: &str) -> Option<&String> {
301 self.nests.get(parent_type)
302 }
303
304 pub fn expand_alias(&self, key: &str) -> Option<&String> {
306 self.aliases.get(key)
307 }
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313
314 #[test]
317 fn test_node_new() {
318 let node = Node::new("User", "user-1", vec![Value::Int(42)]);
319 assert_eq!(node.type_name, "User");
320 assert_eq!(node.id, "user-1");
321 assert_eq!(node.fields.len(), 1);
322 assert!(node.children.is_none());
323 }
324
325 #[test]
326 fn test_node_get_field() {
327 let node = Node::new(
328 "User",
329 "1",
330 vec![Value::Int(1), Value::String("name".to_string().into())],
331 );
332 assert_eq!(node.get_field(0), Some(&Value::Int(1)));
333 assert_eq!(
334 node.get_field(1),
335 Some(&Value::String("name".to_string().into()))
336 );
337 assert_eq!(node.get_field(2), None);
338 }
339
340 #[test]
341 fn test_node_add_child() {
342 let mut parent = Node::new("User", "1", vec![]);
343 let child = Node::new("Post", "p1", vec![]);
344 parent.add_child("Post", child);
345
346 let children = parent.children().unwrap();
347 assert!(children.contains_key("Post"));
348 assert_eq!(children["Post"].len(), 1);
349 }
350
351 #[test]
352 fn test_node_add_multiple_children_same_type() {
353 let mut parent = Node::new("User", "1", vec![]);
354 parent.add_child("Post", Node::new("Post", "p1", vec![]));
355 parent.add_child("Post", Node::new("Post", "p2", vec![]));
356
357 let children = parent.children().unwrap();
358 assert_eq!(children["Post"].len(), 2);
359 }
360
361 #[test]
362 fn test_node_add_children_different_types() {
363 let mut parent = Node::new("User", "1", vec![]);
364 parent.add_child("Post", Node::new("Post", "p1", vec![]));
365 parent.add_child("Comment", Node::new("Comment", "c1", vec![]));
366
367 let children = parent.children().unwrap();
368 assert_eq!(children.len(), 2);
369 assert!(children.contains_key("Post"));
370 assert!(children.contains_key("Comment"));
371 }
372
373 #[test]
374 fn test_node_equality() {
375 let a = Node::new("User", "1", vec![Value::Int(42)]);
376 let b = Node::new("User", "1", vec![Value::Int(42)]);
377 assert_eq!(a, b);
378 }
379
380 #[test]
381 fn test_node_clone() {
382 let mut original = Node::new("User", "1", vec![Value::Int(42)]);
383 original.add_child("Post", Node::new("Post", "p1", vec![]));
384 let cloned = original.clone();
385 assert_eq!(original, cloned);
386 }
387
388 #[test]
389 fn test_node_debug() {
390 let node = Node::new("User", "1", vec![]);
391 let debug = format!("{:?}", node);
392 assert!(debug.contains("User"));
393 assert!(debug.contains("type_name"));
394 }
395
396 #[test]
397 fn test_node_child_count() {
398 let node = Node::with_child_count("User", "1", vec![], 5);
399 assert_eq!(node.get_child_count(), Some(5));
400 }
401
402 #[test]
403 fn test_node_no_child_count() {
404 let node = Node::new("User", "1", vec![]);
405 assert_eq!(node.get_child_count(), None);
406 }
407
408 #[test]
409 fn test_node_set_child_count() {
410 let mut node = Node::new("User", "1", vec![]);
411 node.set_child_count(10);
412 assert_eq!(node.get_child_count(), Some(10));
413 }
414
415 #[test]
416 fn test_node_child_count_saturation() {
417 let node = Node::with_child_count("User", "1", vec![], 100_000);
418 assert_eq!(node.get_child_count(), Some(65535)); }
420
421 #[test]
422 fn test_node_lazy_children() {
423 let node = Node::new("User", "1", vec![]);
424 assert!(node.children.is_none()); }
426
427 #[test]
428 fn test_node_children_accessor() {
429 let mut node = Node::new("User", "1", vec![]);
430 assert!(node.children().is_none());
431
432 node.add_child("Post", Node::new("Post", "p1", vec![]));
433 assert!(node.children().is_some());
434 assert!(node.children().unwrap().contains_key("Post"));
435 }
436
437 #[test]
438 fn test_node_children_mut_accessor() {
439 let mut node = Node::new("User", "1", vec![]);
440 node.add_child("Post", Node::new("Post", "p1", vec![]));
441
442 if let Some(children) = node.children_mut() {
443 children.insert("Comment".to_string(), vec![]);
444 }
445
446 assert!(node.children().unwrap().contains_key("Comment"));
447 }
448
449 #[test]
452 fn test_matrix_list_new() {
453 let list = MatrixList::new("User", vec!["id".to_string(), "name".to_string()]);
454 assert_eq!(list.type_name, "User");
455 assert_eq!(list.schema, vec!["id", "name"]);
456 assert!(list.rows.is_empty());
457 }
458
459 #[test]
460 fn test_matrix_list_add_row() {
461 let mut list = MatrixList::new("User", vec!["id".to_string()]);
462 list.add_row(Node::new("User", "1", vec![]));
463 assert_eq!(list.rows.len(), 1);
464 }
465
466 #[test]
467 fn test_matrix_list_column_count() {
468 let list = MatrixList::new(
469 "User",
470 vec!["a".to_string(), "b".to_string(), "c".to_string()],
471 );
472 assert_eq!(list.column_count(), 3);
473 }
474
475 #[test]
476 fn test_matrix_list_empty_schema() {
477 let list = MatrixList::new("Empty", vec![]);
478 assert_eq!(list.column_count(), 0);
479 }
480
481 #[test]
482 fn test_matrix_list_equality() {
483 let mut a = MatrixList::new("User", vec!["id".to_string()]);
484 a.add_row(Node::new("User", "1", vec![]));
485 let mut b = MatrixList::new("User", vec!["id".to_string()]);
486 b.add_row(Node::new("User", "1", vec![]));
487 assert_eq!(a, b);
488 }
489
490 #[test]
491 fn test_matrix_list_clone() {
492 let mut list = MatrixList::new("User", vec!["id".to_string()]);
493 list.add_row(Node::new("User", "1", vec![]));
494 let cloned = list.clone();
495 assert_eq!(list, cloned);
496 }
497
498 #[test]
499 fn test_matrix_list_with_rows() {
500 let rows = vec![
501 Node::new("User", "1", vec![]),
502 Node::new("User", "2", vec![]),
503 ];
504 let list = MatrixList::with_rows("User", vec!["id".to_string()], rows);
505 assert_eq!(list.rows.len(), 2);
506 }
507
508 #[test]
509 fn test_matrix_list_with_count_hint() {
510 let list = MatrixList::with_count_hint("User", vec!["id".to_string()], 100);
511 assert_eq!(list.count_hint, Some(100));
512 }
513
514 #[test]
517 fn test_item_scalar() {
518 let item = Item::Scalar(Value::Int(42));
519 assert!(item.as_scalar().is_some());
520 assert!(item.as_object().is_none());
521 assert!(item.as_list().is_none());
522 }
523
524 #[test]
525 fn test_item_object() {
526 let mut obj = BTreeMap::new();
527 obj.insert("key".to_string(), Item::Scalar(Value::Int(1)));
528 let item = Item::Object(obj);
529 assert!(item.as_object().is_some());
530 assert!(item.as_scalar().is_none());
531 }
532
533 #[test]
534 fn test_item_list() {
535 let list = MatrixList::new("User", vec!["id".to_string()]);
536 let item = Item::List(list);
537 assert!(item.as_list().is_some());
538 assert!(item.as_scalar().is_none());
539 }
540
541 #[test]
542 fn test_item_as_scalar_returns_value() {
543 let item = Item::Scalar(Value::String("hello".to_string().into()));
544 let value = item.as_scalar().unwrap();
545 assert_eq!(value.as_str(), Some("hello"));
546 }
547
548 #[test]
549 fn test_item_as_object_returns_map() {
550 let mut obj = BTreeMap::new();
551 obj.insert("a".to_string(), Item::Scalar(Value::Int(1)));
552 let item = Item::Object(obj);
553 let map = item.as_object().unwrap();
554 assert!(map.contains_key("a"));
555 }
556
557 #[test]
558 fn test_item_equality() {
559 let a = Item::Scalar(Value::Int(42));
560 let b = Item::Scalar(Value::Int(42));
561 assert_eq!(a, b);
562 }
563
564 #[test]
565 fn test_item_clone() {
566 let item = Item::Scalar(Value::String("test".to_string().into()));
567 let cloned = item.clone();
568 assert_eq!(item, cloned);
569 }
570
571 #[test]
574 fn test_document_new() {
575 let doc = Document::new((1, 0));
576 assert_eq!(doc.version, (1, 0));
577 assert!(doc.aliases.is_empty());
578 assert!(doc.structs.is_empty());
579 assert!(doc.nests.is_empty());
580 assert!(doc.root.is_empty());
581 }
582
583 #[test]
584 fn test_document_get() {
585 let mut doc = Document::new((1, 0));
586 doc.root
587 .insert("key".to_string(), Item::Scalar(Value::Int(42)));
588 assert!(doc.get("key").is_some());
589 assert!(doc.get("missing").is_none());
590 }
591
592 #[test]
593 fn test_document_get_schema() {
594 let mut doc = Document::new((1, 0));
595 doc.structs.insert(
596 "User".to_string(),
597 vec!["id".to_string(), "name".to_string()],
598 );
599 let schema = doc.get_schema("User").unwrap();
600 assert_eq!(schema, &vec!["id".to_string(), "name".to_string()]);
601 assert!(doc.get_schema("Missing").is_none());
602 }
603
604 #[test]
605 fn test_document_get_child_type() {
606 let mut doc = Document::new((1, 0));
607 doc.nests.insert("User".to_string(), "Post".to_string());
608 assert_eq!(doc.get_child_type("User"), Some(&"Post".to_string()));
609 assert!(doc.get_child_type("Post").is_none());
610 }
611
612 #[test]
613 fn test_document_expand_alias() {
614 let mut doc = Document::new((1, 0));
615 doc.aliases.insert("active".to_string(), "true".to_string());
616 assert_eq!(doc.expand_alias("active"), Some(&"true".to_string()));
617 assert!(doc.expand_alias("missing").is_none());
618 }
619
620 #[test]
621 fn test_document_equality() {
622 let a = Document::new((1, 0));
623 let b = Document::new((1, 0));
624 assert_eq!(a, b);
625 }
626
627 #[test]
628 fn test_document_clone() {
629 let mut doc = Document::new((1, 0));
630 doc.aliases.insert("key".to_string(), "value".to_string());
631 let cloned = doc.clone();
632 assert_eq!(doc, cloned);
633 }
634
635 #[test]
636 fn test_document_debug() {
637 let doc = Document::new((1, 0));
638 let debug = format!("{:?}", doc);
639 assert!(debug.contains("version"));
640 assert!(debug.contains("aliases"));
641 }
642
643 #[test]
646 fn test_node_empty_fields() {
647 let node = Node::new("Type", "id", vec![]);
648 assert!(node.fields.is_empty());
649 assert!(node.get_field(0).is_none());
650 }
651
652 #[test]
653 fn test_node_unicode_id() {
654 let node = Node::new("User", "日本語", vec![]);
655 assert_eq!(node.id, "日本語");
656 }
657
658 #[test]
659 fn test_document_version_zero() {
660 let doc = Document::new((0, 0));
661 assert_eq!(doc.version, (0, 0));
662 }
663
664 #[test]
665 fn test_document_large_version() {
666 let doc = Document::new((999, 999));
667 assert_eq!(doc.version, (999, 999));
668 }
669
670 #[test]
671 fn test_nested_items() {
672 let mut inner = BTreeMap::new();
673 inner.insert("nested".to_string(), Item::Scalar(Value::Int(42)));
674
675 let mut outer = BTreeMap::new();
676 outer.insert("inner".to_string(), Item::Object(inner));
677
678 let item = Item::Object(outer);
679 let obj = item.as_object().unwrap();
680 let inner_item = obj.get("inner").unwrap();
681 let inner_obj = inner_item.as_object().unwrap();
682 assert!(inner_obj.contains_key("nested"));
683 }
684
685 #[test]
686 fn test_deeply_nested_nodes() {
687 let mut root = Node::new("A", "a", vec![]);
688 let mut child = Node::new("B", "b", vec![]);
689 child.add_child("C", Node::new("C", "c", vec![]));
690 root.add_child("B", child);
691
692 let children = root.children().unwrap();
693 assert_eq!(children["B"].len(), 1);
694 let b_children = children["B"][0].children().unwrap();
695 assert_eq!(b_children["C"].len(), 1);
696 }
697
698 #[test]
699 fn test_node_default() {
700 let node = Node::default();
701 assert_eq!(node.type_name, "");
702 assert!(node.fields.is_empty());
703 assert!(node.children.is_none());
704 assert_eq!(node.child_count, 0);
705 }
706
707 #[test]
710 fn test_document_schema_versions_empty() {
711 let doc = Document::new((1, 0));
712 assert!(doc.schema_versions.is_empty());
713 }
714
715 #[test]
716 fn test_document_set_schema_version() {
717 use crate::schema_version::SchemaVersion;
718 let mut doc = Document::new((1, 0));
719 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 2, 3));
720 assert_eq!(doc.schema_versions.len(), 1);
721 assert!(doc.schema_versions.contains_key("User"));
722 }
723
724 #[test]
725 fn test_document_get_schema_version() {
726 use crate::schema_version::SchemaVersion;
727 let mut doc = Document::new((1, 0));
728 let version = SchemaVersion::new(2, 0, 0);
729 doc.set_schema_version("Post".to_string(), version);
730 assert_eq!(doc.get_schema_version("Post"), Some(version));
731 assert_eq!(doc.get_schema_version("User"), None);
732 }
733
734 #[test]
735 fn test_document_multiple_schema_versions() {
736 use crate::schema_version::SchemaVersion;
737 let mut doc = Document::new((1, 0));
738 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
739 doc.set_schema_version("Post".to_string(), SchemaVersion::new(2, 1, 0));
740 doc.set_schema_version("Comment".to_string(), SchemaVersion::new(1, 5, 2));
741
742 assert_eq!(doc.schema_versions.len(), 3);
743 assert_eq!(
744 doc.get_schema_version("User"),
745 Some(SchemaVersion::new(1, 0, 0))
746 );
747 assert_eq!(
748 doc.get_schema_version("Post"),
749 Some(SchemaVersion::new(2, 1, 0))
750 );
751 assert_eq!(
752 doc.get_schema_version("Comment"),
753 Some(SchemaVersion::new(1, 5, 2))
754 );
755 }
756
757 #[test]
758 fn test_document_replace_schema_version() {
759 use crate::schema_version::SchemaVersion;
760 let mut doc = Document::new((1, 0));
761 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
762 doc.set_schema_version("User".to_string(), SchemaVersion::new(2, 0, 0));
763
764 assert_eq!(doc.schema_versions.len(), 1);
765 assert_eq!(
766 doc.get_schema_version("User"),
767 Some(SchemaVersion::new(2, 0, 0))
768 );
769 }
770
771 #[test]
772 fn test_document_schema_version_with_clone() {
773 use crate::schema_version::SchemaVersion;
774 let mut doc = Document::new((1, 0));
775 doc.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
776 let cloned = doc.clone();
777
778 assert_eq!(cloned.schema_versions.len(), 1);
779 assert_eq!(
780 cloned.get_schema_version("User"),
781 Some(SchemaVersion::new(1, 0, 0))
782 );
783 }
784
785 #[test]
786 fn test_document_schema_version_equality() {
787 use crate::schema_version::SchemaVersion;
788 let mut a = Document::new((1, 0));
789 a.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
790
791 let mut b = Document::new((1, 0));
792 b.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
793
794 assert_eq!(a, b);
795 }
796
797 #[test]
798 fn test_document_schema_version_inequality() {
799 use crate::schema_version::SchemaVersion;
800 let mut a = Document::new((1, 0));
801 a.set_schema_version("User".to_string(), SchemaVersion::new(1, 0, 0));
802
803 let mut b = Document::new((1, 0));
804 b.set_schema_version("User".to_string(), SchemaVersion::new(2, 0, 0));
805
806 assert_ne!(a, b);
807 }
808}