1use crate::Value;
21use std::collections::BTreeMap;
22
23#[derive(Debug, Clone, PartialEq, Default)]
25pub struct Node {
26 pub type_name: String,
28 pub id: String,
30 pub fields: Vec<Value>,
32 pub children: BTreeMap<String, Vec<Node>>,
34 pub child_count: Option<usize>,
36}
37
38impl Node {
39 pub fn new(type_name: impl Into<String>, id: impl Into<String>, fields: Vec<Value>) -> Self {
41 Self {
42 type_name: type_name.into(),
43 id: id.into(),
44 fields,
45 children: BTreeMap::new(),
46 child_count: None,
47 }
48 }
49
50 pub fn get_field(&self, index: usize) -> Option<&Value> {
52 self.fields.get(index)
53 }
54
55 pub fn add_child(&mut self, child_type: impl Into<String>, child: Node) {
57 self.children
58 .entry(child_type.into())
59 .or_default()
60 .push(child);
61 }
62
63 pub fn set_child_count(&mut self, count: usize) {
65 self.child_count = Some(count);
66 }
67
68 pub fn with_child_count(
70 type_name: impl Into<String>,
71 id: impl Into<String>,
72 fields: Vec<Value>,
73 child_count: usize,
74 ) -> Self {
75 Self {
76 type_name: type_name.into(),
77 id: id.into(),
78 fields,
79 children: BTreeMap::new(),
80 child_count: Some(child_count),
81 }
82 }
83}
84
85#[derive(Debug, Clone, PartialEq)]
87pub struct MatrixList {
88 pub type_name: String,
90 pub schema: Vec<String>,
92 pub rows: Vec<Node>,
94 pub count_hint: Option<usize>,
96}
97
98impl MatrixList {
99 pub fn new(type_name: impl Into<String>, schema: Vec<String>) -> Self {
101 Self {
102 type_name: type_name.into(),
103 schema,
104 rows: Vec::new(),
105 count_hint: None,
106 }
107 }
108
109 pub fn with_rows(
111 type_name: impl Into<String>,
112 schema: Vec<String>,
113 rows: Vec<Node>,
114 ) -> Self {
115 Self {
116 type_name: type_name.into(),
117 schema,
118 rows,
119 count_hint: None,
120 }
121 }
122
123 pub fn with_count_hint(
125 type_name: impl Into<String>,
126 schema: Vec<String>,
127 count_hint: usize,
128 ) -> Self {
129 Self {
130 type_name: type_name.into(),
131 schema,
132 rows: Vec::new(),
133 count_hint: Some(count_hint),
134 }
135 }
136
137 pub fn add_row(&mut self, node: Node) {
139 self.rows.push(node);
140 }
141
142 pub fn column_count(&self) -> usize {
144 self.schema.len()
145 }
146}
147
148#[derive(Debug, Clone, PartialEq)]
150pub enum Item {
151 Scalar(Value),
153 Object(BTreeMap<String, Item>),
155 List(MatrixList),
157}
158
159impl Item {
160 pub fn as_scalar(&self) -> Option<&Value> {
162 match self {
163 Self::Scalar(v) => Some(v),
164 _ => None,
165 }
166 }
167
168 pub fn as_object(&self) -> Option<&BTreeMap<String, Item>> {
170 match self {
171 Self::Object(o) => Some(o),
172 _ => None,
173 }
174 }
175
176 pub fn as_list(&self) -> Option<&MatrixList> {
178 match self {
179 Self::List(l) => Some(l),
180 _ => None,
181 }
182 }
183}
184
185#[derive(Debug, Clone, PartialEq)]
187pub struct Document {
188 pub version: (u32, u32),
190 pub aliases: BTreeMap<String, String>,
192 pub structs: BTreeMap<String, Vec<String>>,
194 pub nests: BTreeMap<String, String>,
196 pub root: BTreeMap<String, Item>,
198}
199
200impl Document {
201 pub fn new(version: (u32, u32)) -> Self {
203 Self {
204 version,
205 aliases: BTreeMap::new(),
206 structs: BTreeMap::new(),
207 nests: BTreeMap::new(),
208 root: BTreeMap::new(),
209 }
210 }
211
212 pub fn get(&self, key: &str) -> Option<&Item> {
214 self.root.get(key)
215 }
216
217 pub fn get_schema(&self, type_name: &str) -> Option<&Vec<String>> {
219 self.structs.get(type_name)
220 }
221
222 pub fn get_child_type(&self, parent_type: &str) -> Option<&String> {
224 self.nests.get(parent_type)
225 }
226
227 pub fn expand_alias(&self, key: &str) -> Option<&String> {
229 self.aliases.get(key)
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
240 fn test_node_new() {
241 let node = Node::new("User", "user-1", vec![Value::Int(42)]);
242 assert_eq!(node.type_name, "User");
243 assert_eq!(node.id, "user-1");
244 assert_eq!(node.fields.len(), 1);
245 assert!(node.children.is_empty());
246 }
247
248 #[test]
249 fn test_node_get_field() {
250 let node = Node::new(
251 "User",
252 "1",
253 vec![Value::Int(1), Value::String("name".to_string())],
254 );
255 assert_eq!(node.get_field(0), Some(&Value::Int(1)));
256 assert_eq!(node.get_field(1), Some(&Value::String("name".to_string())));
257 assert_eq!(node.get_field(2), None);
258 }
259
260 #[test]
261 fn test_node_add_child() {
262 let mut parent = Node::new("User", "1", vec![]);
263 let child = Node::new("Post", "p1", vec![]);
264 parent.add_child("Post", child);
265
266 assert!(parent.children.contains_key("Post"));
267 assert_eq!(parent.children["Post"].len(), 1);
268 }
269
270 #[test]
271 fn test_node_add_multiple_children_same_type() {
272 let mut parent = Node::new("User", "1", vec![]);
273 parent.add_child("Post", Node::new("Post", "p1", vec![]));
274 parent.add_child("Post", Node::new("Post", "p2", vec![]));
275
276 assert_eq!(parent.children["Post"].len(), 2);
277 }
278
279 #[test]
280 fn test_node_add_children_different_types() {
281 let mut parent = Node::new("User", "1", vec![]);
282 parent.add_child("Post", Node::new("Post", "p1", vec![]));
283 parent.add_child("Comment", Node::new("Comment", "c1", vec![]));
284
285 assert_eq!(parent.children.len(), 2);
286 assert!(parent.children.contains_key("Post"));
287 assert!(parent.children.contains_key("Comment"));
288 }
289
290 #[test]
291 fn test_node_equality() {
292 let a = Node::new("User", "1", vec![Value::Int(42)]);
293 let b = Node::new("User", "1", vec![Value::Int(42)]);
294 assert_eq!(a, b);
295 }
296
297 #[test]
298 fn test_node_clone() {
299 let mut original = Node::new("User", "1", vec![Value::Int(42)]);
300 original.add_child("Post", Node::new("Post", "p1", vec![]));
301 let cloned = original.clone();
302 assert_eq!(original, cloned);
303 }
304
305 #[test]
306 fn test_node_debug() {
307 let node = Node::new("User", "1", vec![]);
308 let debug = format!("{:?}", node);
309 assert!(debug.contains("User"));
310 assert!(debug.contains("type_name"));
311 }
312
313 #[test]
316 fn test_matrix_list_new() {
317 let list = MatrixList::new("User", vec!["id".to_string(), "name".to_string()]);
318 assert_eq!(list.type_name, "User");
319 assert_eq!(list.schema, vec!["id", "name"]);
320 assert!(list.rows.is_empty());
321 }
322
323 #[test]
324 fn test_matrix_list_add_row() {
325 let mut list = MatrixList::new("User", vec!["id".to_string()]);
326 list.add_row(Node::new("User", "1", vec![]));
327 assert_eq!(list.rows.len(), 1);
328 }
329
330 #[test]
331 fn test_matrix_list_column_count() {
332 let list = MatrixList::new(
333 "User",
334 vec!["a".to_string(), "b".to_string(), "c".to_string()],
335 );
336 assert_eq!(list.column_count(), 3);
337 }
338
339 #[test]
340 fn test_matrix_list_empty_schema() {
341 let list = MatrixList::new("Empty", vec![]);
342 assert_eq!(list.column_count(), 0);
343 }
344
345 #[test]
346 fn test_matrix_list_equality() {
347 let mut a = MatrixList::new("User", vec!["id".to_string()]);
348 a.add_row(Node::new("User", "1", vec![]));
349 let mut b = MatrixList::new("User", vec!["id".to_string()]);
350 b.add_row(Node::new("User", "1", vec![]));
351 assert_eq!(a, b);
352 }
353
354 #[test]
355 fn test_matrix_list_clone() {
356 let mut list = MatrixList::new("User", vec!["id".to_string()]);
357 list.add_row(Node::new("User", "1", vec![]));
358 let cloned = list.clone();
359 assert_eq!(list, cloned);
360 }
361
362 #[test]
365 fn test_item_scalar() {
366 let item = Item::Scalar(Value::Int(42));
367 assert!(item.as_scalar().is_some());
368 assert!(item.as_object().is_none());
369 assert!(item.as_list().is_none());
370 }
371
372 #[test]
373 fn test_item_object() {
374 let mut obj = BTreeMap::new();
375 obj.insert("key".to_string(), Item::Scalar(Value::Int(1)));
376 let item = Item::Object(obj);
377 assert!(item.as_object().is_some());
378 assert!(item.as_scalar().is_none());
379 }
380
381 #[test]
382 fn test_item_list() {
383 let list = MatrixList::new("User", vec!["id".to_string()]);
384 let item = Item::List(list);
385 assert!(item.as_list().is_some());
386 assert!(item.as_scalar().is_none());
387 }
388
389 #[test]
390 fn test_item_as_scalar_returns_value() {
391 let item = Item::Scalar(Value::String("hello".to_string()));
392 let value = item.as_scalar().unwrap();
393 assert_eq!(value.as_str(), Some("hello"));
394 }
395
396 #[test]
397 fn test_item_as_object_returns_map() {
398 let mut obj = BTreeMap::new();
399 obj.insert("a".to_string(), Item::Scalar(Value::Int(1)));
400 let item = Item::Object(obj);
401 let map = item.as_object().unwrap();
402 assert!(map.contains_key("a"));
403 }
404
405 #[test]
406 fn test_item_equality() {
407 let a = Item::Scalar(Value::Int(42));
408 let b = Item::Scalar(Value::Int(42));
409 assert_eq!(a, b);
410 }
411
412 #[test]
413 fn test_item_clone() {
414 let item = Item::Scalar(Value::String("test".to_string()));
415 let cloned = item.clone();
416 assert_eq!(item, cloned);
417 }
418
419 #[test]
422 fn test_document_new() {
423 let doc = Document::new((1, 0));
424 assert_eq!(doc.version, (1, 0));
425 assert!(doc.aliases.is_empty());
426 assert!(doc.structs.is_empty());
427 assert!(doc.nests.is_empty());
428 assert!(doc.root.is_empty());
429 }
430
431 #[test]
432 fn test_document_get() {
433 let mut doc = Document::new((1, 0));
434 doc.root
435 .insert("key".to_string(), Item::Scalar(Value::Int(42)));
436 assert!(doc.get("key").is_some());
437 assert!(doc.get("missing").is_none());
438 }
439
440 #[test]
441 fn test_document_get_schema() {
442 let mut doc = Document::new((1, 0));
443 doc.structs.insert(
444 "User".to_string(),
445 vec!["id".to_string(), "name".to_string()],
446 );
447 let schema = doc.get_schema("User").unwrap();
448 assert_eq!(schema, &vec!["id".to_string(), "name".to_string()]);
449 assert!(doc.get_schema("Missing").is_none());
450 }
451
452 #[test]
453 fn test_document_get_child_type() {
454 let mut doc = Document::new((1, 0));
455 doc.nests.insert("User".to_string(), "Post".to_string());
456 assert_eq!(doc.get_child_type("User"), Some(&"Post".to_string()));
457 assert!(doc.get_child_type("Post").is_none());
458 }
459
460 #[test]
461 fn test_document_expand_alias() {
462 let mut doc = Document::new((1, 0));
463 doc.aliases.insert("active".to_string(), "true".to_string());
464 assert_eq!(doc.expand_alias("active"), Some(&"true".to_string()));
465 assert!(doc.expand_alias("missing").is_none());
466 }
467
468 #[test]
469 fn test_document_equality() {
470 let a = Document::new((1, 0));
471 let b = Document::new((1, 0));
472 assert_eq!(a, b);
473 }
474
475 #[test]
476 fn test_document_clone() {
477 let mut doc = Document::new((1, 0));
478 doc.aliases.insert("key".to_string(), "value".to_string());
479 let cloned = doc.clone();
480 assert_eq!(doc, cloned);
481 }
482
483 #[test]
484 fn test_document_debug() {
485 let doc = Document::new((1, 0));
486 let debug = format!("{:?}", doc);
487 assert!(debug.contains("version"));
488 assert!(debug.contains("aliases"));
489 }
490
491 #[test]
494 fn test_node_empty_fields() {
495 let node = Node::new("Type", "id", vec![]);
496 assert!(node.fields.is_empty());
497 assert!(node.get_field(0).is_none());
498 }
499
500 #[test]
501 fn test_node_unicode_id() {
502 let node = Node::new("User", "日本語", vec![]);
503 assert_eq!(node.id, "日本語");
504 }
505
506 #[test]
507 fn test_document_version_zero() {
508 let doc = Document::new((0, 0));
509 assert_eq!(doc.version, (0, 0));
510 }
511
512 #[test]
513 fn test_document_large_version() {
514 let doc = Document::new((999, 999));
515 assert_eq!(doc.version, (999, 999));
516 }
517
518 #[test]
519 fn test_nested_items() {
520 let mut inner = BTreeMap::new();
521 inner.insert("nested".to_string(), Item::Scalar(Value::Int(42)));
522
523 let mut outer = BTreeMap::new();
524 outer.insert("inner".to_string(), Item::Object(inner));
525
526 let item = Item::Object(outer);
527 let obj = item.as_object().unwrap();
528 let inner_item = obj.get("inner").unwrap();
529 let inner_obj = inner_item.as_object().unwrap();
530 assert!(inner_obj.contains_key("nested"));
531 }
532
533 #[test]
534 fn test_deeply_nested_nodes() {
535 let mut root = Node::new("A", "a", vec![]);
536 let mut child = Node::new("B", "b", vec![]);
537 child.add_child("C", Node::new("C", "c", vec![]));
538 root.add_child("B", child);
539
540 assert_eq!(root.children["B"].len(), 1);
541 assert_eq!(root.children["B"][0].children["C"].len(), 1);
542 }
543}