1pub mod constructor;
2pub mod interpreter_sink;
3pub mod node;
4pub mod source_constructor;
5
6use crate::document::node::{NodeArray, NodeTuple};
7use crate::prelude_internal::*;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct NodeId(pub usize);
11
12#[derive(Debug, Clone)]
13pub struct EureDocument {
14 pub(crate) root: NodeId,
15 nodes: Vec<Node>,
16}
17
18#[derive(Debug, PartialEq, thiserror::Error, Clone)]
19#[error("Insert error: {kind} at {path}")]
20pub struct InsertError {
21 pub kind: InsertErrorKind,
22 pub path: EurePath,
23}
24
25#[derive(Debug, PartialEq, thiserror::Error, Clone)]
26pub enum InsertErrorKind {
27 #[error("Already assigned")]
28 AlreadyAssigned { key: ObjectKey },
29 #[error("Extension already assigned: {identifier}")]
30 AlreadyAssignedExtension { identifier: Identifier },
31 #[error("Expected array")]
32 ExpectedArray,
33 #[error("Array index invalid: expected {expected_index} but got {index}")]
34 ArrayIndexInvalid { index: usize, expected_index: usize },
35 #[error("Expected map")]
36 ExpectedMap,
37 #[error("Expected tuple")]
38 ExpectedTuple,
39 #[error("Tuple index invalid: expected {expected_index} but got {index}")]
40 TupleIndexInvalid { index: u8, expected_index: usize },
41 #[error("Binding target already has a value")]
42 BindingTargetHasValue,
43 #[error("Scope error: {0}")]
44 ScopeError(#[from] constructor::ScopeError),
45 #[error("Constructor error: {0}")]
46 ConstructorError(#[from] ConstructorError),
47}
48
49#[derive(Debug, PartialEq, thiserror::Error, Clone)]
51pub enum ConstructorError {
52 #[error("set_block_value called without a preceding bind operation")]
53 MissingBindBeforeSetBlockValue,
54 #[error("end_binding_value called without a preceding bind operation")]
55 MissingBindBeforeEndBindingValue,
56 #[error("end_binding_block called without a preceding end_eure_block")]
57 MissingEndEureBlockBeforeEndBindingBlock,
58 #[error("end_section_block called without a preceding end_eure_block")]
59 MissingEndEureBlockBeforeEndSectionBlock,
60 #[error("end_eure_block called but builder stack is not in EureBlock state")]
61 InvalidBuilderStackForEndEureBlock,
62 #[error("end_section_items called but builder stack is not in SectionItems state")]
63 InvalidBuilderStackForEndSectionItems,
64 #[error("ArrayIndex must follow a key segment; standalone [] is not valid")]
65 StandaloneArrayIndex,
66}
67
68impl Default for EureDocument {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl PartialEq for EureDocument {
75 fn eq(&self, other: &Self) -> bool {
76 self.nodes_equal(self.root, other, other.root)
77 }
78}
79
80impl EureDocument {
81 fn nodes_equal(&self, id1: NodeId, other: &EureDocument, id2: NodeId) -> bool {
83 let node1 = &self.nodes[id1.0];
84 let node2 = &other.nodes[id2.0];
85
86 if node1.extensions.len() != node2.extensions.len() {
88 return false;
89 }
90
91 for (key1, &child_id1) in &node1.extensions {
92 match node2.extensions.get(key1) {
93 Some(&child_id2) => {
94 if !self.nodes_equal(child_id1, other, child_id2) {
95 return false;
96 }
97 }
98 None => return false,
99 }
100 }
101
102 self.node_values_equal(&node1.content, other, &node2.content)
104 }
105
106 fn node_values_equal(
108 &self,
109 value1: &NodeValue,
110 other: &EureDocument,
111 value2: &NodeValue,
112 ) -> bool {
113 match (value1, value2) {
114 (NodeValue::Hole(l1), NodeValue::Hole(l2)) => l1 == l2,
115 (NodeValue::Primitive(p1), NodeValue::Primitive(p2)) => p1 == p2,
116 (NodeValue::Array(arr1), NodeValue::Array(arr2)) => {
117 self.node_arrays_equal(arr1, other, arr2)
118 }
119 (NodeValue::Tuple(tup1), NodeValue::Tuple(tup2)) => {
120 self.node_tuples_equal(tup1, other, tup2)
121 }
122 (NodeValue::Map(map1), NodeValue::Map(map2)) => self.node_maps_equal(map1, other, map2),
123 _ => false,
124 }
125 }
126
127 fn node_arrays_equal(&self, arr1: &NodeArray, other: &EureDocument, arr2: &NodeArray) -> bool {
128 if arr1.len() != arr2.len() {
129 return false;
130 }
131
132 for (child_id1, child_id2) in arr1.iter().zip(arr2.iter()) {
133 if !self.nodes_equal(*child_id1, other, *child_id2) {
134 return false;
135 }
136 }
137
138 true
139 }
140
141 fn node_tuples_equal(&self, tup1: &NodeTuple, other: &EureDocument, tup2: &NodeTuple) -> bool {
142 if tup1.len() != tup2.len() {
143 return false;
144 }
145
146 for (child_id1, child_id2) in tup1.iter().zip(tup2.iter()) {
147 if !self.nodes_equal(*child_id1, other, *child_id2) {
148 return false;
149 }
150 }
151
152 true
153 }
154
155 fn node_maps_equal(&self, map1: &NodeMap, other: &EureDocument, map2: &NodeMap) -> bool {
156 if map1.len() != map2.len() {
157 return false;
158 }
159
160 for (key1, &child_id1) in map1.iter() {
161 match map2.get(key1) {
162 Some(&child_id2) => {
163 if !self.nodes_equal(child_id1, other, child_id2) {
164 return false;
165 }
166 }
167 None => return false,
168 }
169 }
170
171 true
172 }
173
174 pub fn new() -> Self {
175 Self {
176 root: NodeId(0),
177 nodes: vec![Node {
178 content: NodeValue::hole(),
179 extensions: Map::new(),
180 }],
181 }
182 }
183
184 pub fn new_empty() -> Self {
185 Self {
186 root: NodeId(0),
187 nodes: vec![Node {
188 content: NodeValue::Map(Default::default()),
189 extensions: Map::new(),
190 }],
191 }
192 }
193
194 pub fn new_primitive(value: PrimitiveValue) -> Self {
195 Self {
196 root: NodeId(0),
197 nodes: vec![Node {
198 content: NodeValue::Primitive(value),
199 extensions: Map::new(),
200 }],
201 }
202 }
203
204 pub fn root(&self) -> &Node {
205 &self.nodes[self.root.0]
206 }
207
208 pub fn get_root_id(&self) -> NodeId {
209 self.root
210 }
211
212 pub fn node(&self, id: NodeId) -> &Node {
213 &self.nodes[id.0]
214 }
215
216 pub fn get_node(&self, id: NodeId) -> Option<&Node> {
217 self.nodes.get(id.0)
218 }
219
220 pub fn node_mut(&mut self, id: NodeId) -> &mut Node {
221 &mut self.nodes[id.0]
222 }
223
224 pub fn get_node_mut(&mut self, id: NodeId) -> Option<&mut Node> {
225 self.nodes.get_mut(id.0)
226 }
227
228 pub fn create_node(&mut self, new: NodeValue) -> NodeId {
229 self.nodes.push(Node {
230 content: new,
231 extensions: Map::new(),
232 });
233 NodeId(self.nodes.len() - 1)
234 }
235
236 pub fn create_node_uninitialized(&mut self) -> NodeId {
237 self.create_node(NodeValue::hole())
238 }
239
240 pub fn set_content(&mut self, node_id: NodeId, content: NodeValue) {
242 self.nodes[node_id.0].content = content;
243 }
244
245 pub fn add_child_by_segment(
246 &mut self,
247 segment: PathSegment,
248 parent_node_id: NodeId,
249 ) -> Result<NodeMut<'_>, InsertErrorKind> {
250 match segment {
251 PathSegment::Ident(identifier) => {
252 self.add_map_child(ObjectKey::String(identifier.into_string()), parent_node_id)
253 }
254 PathSegment::Value(object_key) => self.add_map_child(object_key, parent_node_id),
255 PathSegment::Extension(identifier) => self.add_extension(identifier, parent_node_id),
256 PathSegment::TupleIndex(index) => self.add_tuple_element(index, parent_node_id),
257 PathSegment::ArrayIndex(index) => self.add_array_element(index, parent_node_id),
258 }
259 }
260
261 pub fn add_map_child(
262 &mut self,
263 object_key: ObjectKey,
264 parent_node_id: NodeId,
265 ) -> Result<NodeMut<'_>, InsertErrorKind> {
266 let node_id = self.create_node_uninitialized();
267 let node = self.node_mut(parent_node_id);
268 let map = node.require_map()?;
269 map.add(object_key, node_id)?;
270 Ok(NodeMut::new(self, node_id))
271 }
272
273 pub fn add_extension(
274 &mut self,
275 identifier: Identifier,
276 parent_node_id: NodeId,
277 ) -> Result<NodeMut<'_>, InsertErrorKind> {
278 let node_id = self.create_node_uninitialized();
279 let node = self.node_mut(parent_node_id);
280 if node.extensions.contains_key(&identifier) {
281 return Err(InsertErrorKind::AlreadyAssignedExtension { identifier });
282 }
283 node.extensions.insert(identifier, node_id);
284 Ok(NodeMut::new(self, node_id))
285 }
286
287 pub fn add_tuple_element(
288 &mut self,
289 index: u8,
290 parent_node_id: NodeId,
291 ) -> Result<NodeMut<'_>, InsertErrorKind> {
292 let node_id = self.create_node_uninitialized();
293 let node = self.node_mut(parent_node_id);
294 let tuple = node.require_tuple()?;
295 tuple.add_at(index, node_id)?;
296 Ok(NodeMut::new(self, node_id))
297 }
298
299 pub fn add_array_element(
300 &mut self,
301 index: Option<usize>,
302 parent_node_id: NodeId,
303 ) -> Result<NodeMut<'_>, InsertErrorKind> {
304 let node_id = self.create_node_uninitialized();
305 let node = self.node_mut(parent_node_id);
306 let array = node.require_array()?;
307 if let Some(index) = index {
308 array.add_at(index, node_id)?;
309 } else {
310 array.push(node_id)?;
311 }
312 Ok(NodeMut::new(self, node_id))
313 }
314
315 pub fn resolve_child_by_segment(
320 &mut self,
321 segment: PathSegment,
322 parent_node_id: NodeId,
323 ) -> Result<NodeMut<'_>, InsertErrorKind> {
324 let node = self.node(parent_node_id);
326
327 let existing = match &segment {
328 PathSegment::Ident(identifier) => node
329 .as_map()
330 .and_then(|m| m.get(&ObjectKey::String(identifier.clone().into_string())))
331 .copied(),
332 PathSegment::Value(object_key) => {
333 node.as_map().and_then(|m| m.get(object_key)).copied()
334 }
335 PathSegment::Extension(identifier) => node.get_extension(identifier),
336 PathSegment::TupleIndex(index) => node.as_tuple().and_then(|t| t.get(*index as usize)),
337 PathSegment::ArrayIndex(Some(index)) => node.as_array().and_then(|a| a.get(*index)),
338 PathSegment::ArrayIndex(None) => None, };
340
341 if let Some(node_id) = existing {
343 return Ok(NodeMut::new(self, node_id));
344 }
345
346 self.add_child_by_segment(segment, parent_node_id)
348 }
349
350 pub fn node_subtree_to_document(&self, node_id: NodeId) -> EureDocument {
352 let mut result = EureDocument::new();
353 let root_id = result.get_root_id();
354 self.copy_subtree(node_id, &mut result, root_id);
355 result
356 }
357
358 pub fn copy_subtree(&self, src_id: NodeId, dst: &mut EureDocument, dst_id: NodeId) {
359 let src_node = self.node(src_id);
360
361 match &src_node.content {
365 NodeValue::Hole(label) => {
366 dst.node_mut(dst_id).content = NodeValue::Hole(label.clone());
367 }
368 NodeValue::Primitive(p) => {
369 dst.node_mut(dst_id).content = NodeValue::Primitive(p.clone());
370 }
371 NodeValue::Array(arr) => {
372 dst.node_mut(dst_id).content = NodeValue::empty_array();
373 for &child_src_id in arr.iter() {
374 if let Ok(result) = dst.add_array_element(None, dst_id) {
375 let child_dst_id = result.node_id;
376 self.copy_subtree(child_src_id, dst, child_dst_id);
377 }
378 }
379 }
380 NodeValue::Tuple(tuple) => {
381 dst.node_mut(dst_id).content = NodeValue::empty_tuple();
382 for (idx, &child_src_id) in tuple.iter().enumerate() {
383 if let Ok(result) = dst.add_tuple_element(idx as u8, dst_id) {
384 let child_dst_id = result.node_id;
385 self.copy_subtree(child_src_id, dst, child_dst_id);
386 }
387 }
388 }
389 NodeValue::Map(map) => {
390 dst.node_mut(dst_id).content = NodeValue::empty_map();
391 for (key, &child_src_id) in map.iter() {
392 if let Ok(result) = dst.add_map_child(key.clone(), dst_id) {
393 let child_dst_id = result.node_id;
394 self.copy_subtree(child_src_id, dst, child_dst_id);
395 }
396 }
397 }
398 }
399
400 let extensions: Vec<_> = self
402 .node(src_id)
403 .extensions
404 .iter()
405 .map(|(k, v)| (k.clone(), *v))
406 .collect();
407 for (ext_name, ext_src_id) in extensions {
408 if let Ok(result) = dst.add_extension(ext_name, dst_id) {
409 let ext_dst_id = result.node_id;
410 self.copy_subtree(ext_src_id, dst, ext_dst_id);
411 }
412 }
413 }
414}
415
416impl EureDocument {
418 pub fn replace_with_primitive(&mut self, value: PrimitiveValue) -> Result<(), InsertErrorKind> {
419 self.nodes.clear();
420 self.nodes[self.root.0].content = NodeValue::Primitive(value);
421 Ok(())
422 }
423
424 pub fn reset_as_map(&mut self) -> Result<(), InsertErrorKind> {
425 self.nodes.clear();
426 self.nodes[self.root.0].content = NodeValue::Map(Default::default());
427 Ok(())
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 fn identifier(s: &str) -> Identifier {
436 s.parse().unwrap()
437 }
438
439 #[test]
440 fn test_add_map_child_success() {
441 let mut doc = EureDocument::new();
442 let map_id = {
443 let doc: &mut EureDocument = &mut doc;
444 doc.create_node(NodeValue::empty_map())
445 };
446 let key = ObjectKey::String("test_key".to_string());
447
448 let child_id = doc
449 .add_map_child(key.clone(), map_id)
450 .expect("Failed to add map child")
451 .node_id;
452
453 let map = doc.node(map_id).as_map().expect("Expected map");
454 assert_eq!(map.get(&key), Some(&child_id));
455 }
456
457 #[test]
458 fn test_add_map_child_error_expected_map() {
459 let mut doc = EureDocument::new();
460 let primitive_id = {
461 let doc: &mut EureDocument = &mut doc;
462 doc.create_node(NodeValue::Primitive(PrimitiveValue::Null))
463 };
464 let key = ObjectKey::String("test".to_string());
465
466 let result = doc.add_map_child(key, primitive_id);
467 assert_eq!(result.err(), Some(InsertErrorKind::ExpectedMap));
468 }
469
470 #[test]
471 fn test_add_map_child_error_already_assigned() {
472 let mut doc = EureDocument::new();
473 let root_id = doc.get_root_id();
474 let key = ObjectKey::String("test".to_string());
475
476 let _result1 = doc
477 .add_map_child(key.clone(), root_id)
478 .expect("First add should succeed");
479
480 let result2 = doc.add_map_child(key.clone(), root_id);
481 assert_eq!(
482 result2.err(),
483 Some(InsertErrorKind::AlreadyAssigned { key })
484 );
485 }
486
487 #[test]
488 fn test_add_extension_success_multiple() {
489 let mut doc = EureDocument::new();
490 let root_id = doc.get_root_id();
491 let id1 = identifier("ext1");
492 let id2 = identifier("ext2");
493
494 let node_id1 = doc
495 .add_extension(id1.clone(), root_id)
496 .expect("Failed to add extension")
497 .node_id;
498
499 let node_id2 = doc
500 .add_extension(id2.clone(), root_id)
501 .expect("Failed to add extension")
502 .node_id;
503
504 let node = doc.node(root_id);
505 assert_eq!(node.extensions.get(&id1), Some(&node_id1));
506 assert_eq!(node.extensions.get(&id2), Some(&node_id2));
507 }
508
509 #[test]
510 fn test_add_extension_success() {
511 let mut doc = EureDocument::new();
512 let primitive_id = {
513 let doc: &mut EureDocument = &mut doc;
514 doc.create_node(NodeValue::Primitive(PrimitiveValue::Null))
515 };
516 let identifier = identifier("ext");
517
518 let node_id = doc
519 .add_extension(identifier.clone(), primitive_id)
520 .expect("Failed to add extension")
521 .node_id;
522
523 let node = doc.node(primitive_id);
524 assert_eq!(node.extensions.get(&identifier), Some(&node_id));
525 }
526
527 #[test]
528 fn test_add_extension_error_already_assigned() {
529 let mut doc = EureDocument::new();
530 let map_id = {
531 let doc: &mut EureDocument = &mut doc;
532 doc.create_node(NodeValue::empty_map())
533 };
534 let identifier = identifier("ext");
535
536 let _result1 = doc
537 .add_extension(identifier.clone(), map_id)
538 .expect("First add should succeed");
539
540 let result2 = doc.add_extension(identifier.clone(), map_id);
541 assert_eq!(
542 result2.err(),
543 Some(InsertErrorKind::AlreadyAssignedExtension { identifier })
544 );
545 }
546
547 #[test]
548 fn test_add_tuple_element_success_index_0() {
549 let mut doc = EureDocument::new();
550 let tuple_id = {
551 let doc: &mut EureDocument = &mut doc;
552 doc.create_node(NodeValue::empty_tuple())
553 };
554
555 let node_id = doc
556 .add_tuple_element(0, tuple_id)
557 .expect("Failed to add tuple element")
558 .node_id;
559
560 let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
561 assert_eq!(tuple.to_vec(), vec![node_id]);
562 }
563
564 #[test]
565 fn test_add_tuple_element_success_sequential() {
566 let mut doc = EureDocument::new();
567 let tuple_id = {
568 let doc: &mut EureDocument = &mut doc;
569 doc.create_node(NodeValue::empty_tuple())
570 };
571
572 let node_id1 = doc
573 .add_tuple_element(0, tuple_id)
574 .expect("Failed to add tuple element")
575 .node_id;
576
577 let node_id2 = doc
578 .add_tuple_element(1, tuple_id)
579 .expect("Failed to add tuple element")
580 .node_id;
581
582 let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
583 assert_eq!(tuple.to_vec(), vec![node_id1, node_id2]);
584 }
585
586 #[test]
587 fn test_add_tuple_element_error_expected_tuple() {
588 let mut doc = EureDocument::new();
589 let map_id = {
590 let doc: &mut EureDocument = &mut doc;
591 doc.create_node(NodeValue::empty_map())
592 };
593
594 let result = doc.add_tuple_element(0, map_id);
595 assert_eq!(result.err(), Some(InsertErrorKind::ExpectedTuple));
596 }
597
598 #[test]
599 fn test_add_tuple_element_error_invalid_index() {
600 let mut doc = EureDocument::new();
601 let tuple_id = {
602 let doc: &mut EureDocument = &mut doc;
603 doc.create_node(NodeValue::empty_tuple())
604 };
605
606 let result = doc.add_tuple_element(1, tuple_id);
607 assert_eq!(
608 result.err(),
609 Some(InsertErrorKind::TupleIndexInvalid {
610 index: 1,
611 expected_index: 0
612 })
613 );
614 }
615
616 #[test]
617 fn test_add_array_element_success_push() {
618 let mut doc = EureDocument::new();
619 let array_id = {
620 let doc: &mut EureDocument = &mut doc;
621 doc.create_node(NodeValue::empty_array())
622 };
623
624 let node_id = doc
625 .add_array_element(None, array_id)
626 .expect("Failed to add array element")
627 .node_id;
628
629 let array = doc.node(array_id).as_array().expect("Expected array");
630 assert_eq!(array.to_vec(), vec![node_id]);
631 }
632
633 #[test]
634 fn test_add_array_element_success_at_index() {
635 let mut doc = EureDocument::new();
636 let array_id = {
637 let doc: &mut EureDocument = &mut doc;
638 doc.create_node(NodeValue::empty_array())
639 };
640
641 let node_id1 = doc
642 .add_array_element(Some(0), array_id)
643 .expect("Failed to add array element")
644 .node_id;
645
646 let node_id2 = doc
647 .add_array_element(Some(1), array_id)
648 .expect("Failed to add array element")
649 .node_id;
650
651 let array = doc.node(array_id).as_array().expect("Expected array");
652 assert_eq!(array.to_vec(), vec![node_id1, node_id2]);
653 }
654
655 #[test]
656 fn test_add_array_element_error_expected_array() {
657 let mut doc = EureDocument::new();
658 let map_id = {
659 let doc: &mut EureDocument = &mut doc;
660 doc.create_node(NodeValue::empty_map())
661 };
662
663 let result = doc.add_array_element(None, map_id);
664 assert_eq!(result.err(), Some(InsertErrorKind::ExpectedArray));
665 }
666
667 #[test]
668 fn test_add_array_element_error_invalid_index() {
669 let mut doc = EureDocument::new();
670 let array_id = {
671 let doc: &mut EureDocument = &mut doc;
672 doc.create_node(NodeValue::empty_array())
673 };
674
675 let result = doc.add_array_element(Some(1), array_id);
676 assert_eq!(
677 result.err(),
678 Some(InsertErrorKind::ArrayIndexInvalid {
679 index: 1,
680 expected_index: 0
681 })
682 );
683 }
684
685 #[test]
686 fn test_add_child_by_segment_ident() {
687 let mut doc = EureDocument::new();
688 let root_id = doc.get_root_id();
689 let identifier = identifier("test");
690 let segment = PathSegment::Ident(identifier.clone());
691
692 let result = doc.add_child_by_segment(segment, root_id);
693 assert!(result.is_ok());
694
695 let map = doc.node(root_id).as_map().expect("Expected map");
696 let key = ObjectKey::String(identifier.into_string());
697 assert!(map.get(&key).is_some());
698 }
699
700 #[test]
701 fn test_add_child_by_segment_value() {
702 let mut doc = EureDocument::new();
703 let root_id = doc.get_root_id();
704 let key = ObjectKey::String("test".to_string());
705 let segment = PathSegment::Value(key.clone());
706
707 let result = doc.add_child_by_segment(segment, root_id);
708 assert!(result.is_ok());
709
710 let map = doc.node(root_id).as_map().expect("Expected map");
711 assert!(map.get(&key).is_some());
712 }
713
714 #[test]
715 fn test_add_child_by_segment_extension() {
716 let mut doc = EureDocument::new();
717 let root_id = doc.get_root_id();
718 let identifier = identifier("ext");
719 let segment = PathSegment::Extension(identifier.clone());
720
721 let result = doc.add_child_by_segment(segment, root_id);
722 assert!(result.is_ok());
723
724 let node = doc.node(root_id);
725 assert!(node.extensions.contains_key(&identifier));
726 }
727
728 #[test]
729 fn test_add_child_by_segment_tuple_index() {
730 let mut doc = EureDocument::new();
731 let tuple_id = {
732 let doc: &mut EureDocument = &mut doc;
733 doc.create_node(NodeValue::empty_tuple())
734 };
735 let segment = PathSegment::TupleIndex(0);
736
737 let result = doc.add_child_by_segment(segment, tuple_id);
738 assert!(result.is_ok());
739
740 let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
741 assert_eq!(tuple.len(), 1);
742 }
743
744 #[test]
745 fn test_add_child_by_segment_array_index_none() {
746 let mut doc = EureDocument::new();
747 let array_id = {
748 let doc: &mut EureDocument = &mut doc;
749 doc.create_node(NodeValue::empty_array())
750 };
751 let segment = PathSegment::ArrayIndex(None);
752
753 let result = doc.add_child_by_segment(segment, array_id);
754 assert!(result.is_ok());
755
756 let array = doc.node(array_id).as_array().expect("Expected array");
757 assert_eq!(array.len(), 1);
758 }
759
760 #[test]
761 fn test_add_child_by_segment_array_index_some() {
762 let mut doc = EureDocument::new();
763 let array_id = {
764 let doc: &mut EureDocument = &mut doc;
765 doc.create_node(NodeValue::empty_array())
766 };
767 let segment = PathSegment::ArrayIndex(Some(0));
768
769 let result = doc.add_child_by_segment(segment, array_id);
770 assert!(result.is_ok());
771
772 let array = doc.node(array_id).as_array().expect("Expected array");
773 assert_eq!(array.len(), 1);
774 }
775
776 #[test]
777 fn test_resolve_ident_idempotent() {
778 let mut doc = EureDocument::new();
779 let root_id = doc.get_root_id();
780 let identifier = identifier("field");
781
782 let node_id1 = doc
784 .resolve_child_by_segment(PathSegment::Ident(identifier.clone()), root_id)
785 .expect("First call failed")
786 .node_id;
787
788 let node_id2 = doc
790 .resolve_child_by_segment(PathSegment::Ident(identifier), root_id)
791 .expect("Second call failed")
792 .node_id;
793
794 assert_eq!(node_id1, node_id2);
795 }
796
797 #[test]
798 fn test_resolve_value_idempotent() {
799 let mut doc = EureDocument::new();
800 let root_id = doc.get_root_id();
801 let object_key = ObjectKey::String("key".to_string());
802
803 let node_id1 = doc
805 .resolve_child_by_segment(PathSegment::Value(object_key.clone()), root_id)
806 .expect("First call failed")
807 .node_id;
808
809 let node_id2 = doc
811 .resolve_child_by_segment(PathSegment::Value(object_key), root_id)
812 .expect("Second call failed")
813 .node_id;
814
815 assert_eq!(node_id1, node_id2);
816 }
817
818 #[test]
819 fn test_resolve_extension_idempotent() {
820 let mut doc = EureDocument::new();
821 let root_id = doc.get_root_id();
822 let identifier = identifier("ext");
823
824 let node_id1 = doc
826 .resolve_child_by_segment(PathSegment::Extension(identifier.clone()), root_id)
827 .expect("First call failed")
828 .node_id;
829
830 let node_id2 = doc
832 .resolve_child_by_segment(PathSegment::Extension(identifier), root_id)
833 .expect("Second call failed")
834 .node_id;
835
836 assert_eq!(node_id1, node_id2);
837 }
838
839 #[test]
840 fn test_resolve_tuple_index_idempotent() {
841 let mut doc = EureDocument::new();
842 let parent_id = doc.create_node_uninitialized();
843
844 let node_id1 = doc
846 .resolve_child_by_segment(PathSegment::TupleIndex(0), parent_id)
847 .expect("First call failed")
848 .node_id;
849
850 let node_id2 = doc
852 .resolve_child_by_segment(PathSegment::TupleIndex(0), parent_id)
853 .expect("Second call failed")
854 .node_id;
855
856 assert_eq!(node_id1, node_id2);
857 }
858
859 #[test]
860 fn test_resolve_array_index_some_idempotent() {
861 let mut doc = EureDocument::new();
862 let parent_id = doc.create_node_uninitialized();
863
864 let node_id1 = doc
866 .resolve_child_by_segment(PathSegment::ArrayIndex(Some(0)), parent_id)
867 .expect("First call failed")
868 .node_id;
869
870 let node_id2 = doc
872 .resolve_child_by_segment(PathSegment::ArrayIndex(Some(0)), parent_id)
873 .expect("Second call failed")
874 .node_id;
875
876 assert_eq!(node_id1, node_id2);
877 }
878
879 #[test]
880 fn test_resolve_array_index_none_always_creates_new() {
881 let mut doc = EureDocument::new();
882 let parent_id = doc.create_node_uninitialized();
883
884 let node_id1 = doc
886 .resolve_child_by_segment(PathSegment::ArrayIndex(None), parent_id)
887 .expect("First call failed")
888 .node_id;
889
890 let node_id2 = doc
892 .resolve_child_by_segment(PathSegment::ArrayIndex(None), parent_id)
893 .expect("Second call failed")
894 .node_id;
895
896 assert_ne!(node_id1, node_id2);
898
899 let array = doc.node(parent_id).as_array().expect("Expected array");
901 assert_eq!(array.len(), 2);
902 assert_eq!(array.get(0).unwrap(), node_id1);
903 assert_eq!(array.get(1).unwrap(), node_id2);
904 }
905
906 #[test]
907 fn test_get_node_with_valid_id() {
908 let mut doc = EureDocument::new();
909 let node_id = doc.create_node(NodeValue::Primitive(PrimitiveValue::Null));
910
911 let result = doc.get_node(node_id);
912 assert!(result.is_some());
913
914 let node = result.unwrap();
915 assert_eq!(node.content, NodeValue::Primitive(PrimitiveValue::Null));
916 }
917
918 #[test]
919 fn test_get_node_with_invalid_id() {
920 let doc = EureDocument::new();
921 let invalid_id = NodeId(9999);
923
924 let result = doc.get_node(invalid_id);
925 assert!(result.is_none());
926 }
927
928 #[test]
929 fn test_get_node_mut_with_valid_id() {
930 let mut doc = EureDocument::new();
931 let node_id = doc.create_node(NodeValue::Primitive(PrimitiveValue::Null));
932
933 let result = doc.get_node_mut(node_id);
934 assert!(result.is_some());
935
936 let node = result.unwrap();
938 node.content = NodeValue::Primitive(PrimitiveValue::Bool(true));
939
940 assert_eq!(
942 doc.node(node_id).content,
943 NodeValue::Primitive(PrimitiveValue::Bool(true))
944 );
945 }
946
947 #[test]
948 fn test_get_node_mut_with_invalid_id() {
949 let mut doc = EureDocument::new();
950 let invalid_id = NodeId(9999);
952
953 let result = doc.get_node_mut(invalid_id);
954 assert!(result.is_none());
955 }
956
957 #[test]
958 fn test_partialeq_empty_documents() {
959 let doc1 = EureDocument::new();
960 let doc2 = EureDocument::new();
961 assert_eq!(doc1, doc2);
962 }
963
964 #[test]
965 fn test_partialeq_primitive_documents() {
966 let doc1 = EureDocument::new_primitive(PrimitiveValue::Bool(true));
967 let doc2 = EureDocument::new_primitive(PrimitiveValue::Bool(true));
968 let doc3 = EureDocument::new_primitive(PrimitiveValue::Bool(false));
969
970 assert_eq!(doc1, doc2);
971 assert_ne!(doc1, doc3);
972 }
973
974 #[test]
975 fn test_partialeq_with_map_children() {
976 let mut doc1 = EureDocument::new();
977 let mut doc2 = EureDocument::new();
978
979 let root1 = doc1.get_root_id();
980 let root2 = doc2.get_root_id();
981
982 let key = ObjectKey::String("test".to_string());
983
984 doc1.add_map_child(key.clone(), root1)
985 .expect("Failed to add child");
986 doc2.add_map_child(key.clone(), root2)
987 .expect("Failed to add child");
988
989 assert_eq!(doc1, doc2);
990 }
991
992 #[test]
993 fn test_partialeq_with_different_map_children() {
994 let mut doc1 = EureDocument::new();
995 let mut doc2 = EureDocument::new();
996
997 let root1 = doc1.get_root_id();
998 let root2 = doc2.get_root_id();
999
1000 doc1.add_map_child(ObjectKey::String("key1".to_string()), root1)
1001 .expect("Failed to add child");
1002 doc2.add_map_child(ObjectKey::String("key2".to_string()), root2)
1003 .expect("Failed to add child");
1004
1005 assert_ne!(doc1, doc2);
1006 }
1007
1008 #[test]
1009 fn test_partialeq_with_extensions() {
1010 let mut doc1 = EureDocument::new();
1011 let mut doc2 = EureDocument::new();
1012
1013 let root1 = doc1.get_root_id();
1014 let root2 = doc2.get_root_id();
1015
1016 let ext_id = identifier("ext");
1017
1018 doc1.add_extension(ext_id.clone(), root1)
1019 .expect("Failed to add extension");
1020 doc2.add_extension(ext_id.clone(), root2)
1021 .expect("Failed to add extension");
1022
1023 assert_eq!(doc1, doc2);
1024 }
1025
1026 #[test]
1027 fn test_partialeq_with_different_extensions() {
1028 let mut doc1 = EureDocument::new();
1029 let mut doc2 = EureDocument::new();
1030
1031 let root1 = doc1.get_root_id();
1032 let root2 = doc2.get_root_id();
1033
1034 doc1.add_extension(identifier("ext1"), root1)
1035 .expect("Failed to add extension");
1036 doc2.add_extension(identifier("ext2"), root2)
1037 .expect("Failed to add extension");
1038
1039 assert_ne!(doc1, doc2);
1040 }
1041
1042 #[test]
1043 fn test_partialeq_with_arrays() {
1044 let mut doc1 = EureDocument::new();
1045 let mut doc2 = EureDocument::new();
1046
1047 let array_id1 = doc1.create_node(NodeValue::empty_array());
1049 doc1.add_array_element(None, array_id1)
1050 .expect("Failed to add array element");
1051 doc1.root = array_id1;
1052
1053 let array_id2 = doc2.create_node(NodeValue::empty_array());
1055 doc2.add_array_element(None, array_id2)
1056 .expect("Failed to add array element");
1057 doc2.root = array_id2;
1058
1059 assert_eq!(doc1, doc2);
1060 }
1061
1062 #[test]
1063 fn test_partialeq_with_tuples() {
1064 let mut doc1 = EureDocument::new();
1065 let mut doc2 = EureDocument::new();
1066
1067 let tuple_id1 = doc1.create_node(NodeValue::empty_tuple());
1069 doc1.add_tuple_element(0, tuple_id1)
1070 .expect("Failed to add tuple element");
1071 doc1.root = tuple_id1;
1072
1073 let tuple_id2 = doc2.create_node(NodeValue::empty_tuple());
1075 doc2.add_tuple_element(0, tuple_id2)
1076 .expect("Failed to add tuple element");
1077 doc2.root = tuple_id2;
1078
1079 assert_eq!(doc1, doc2);
1080 }
1081
1082 #[test]
1083 fn test_partialeq_nested_structure() {
1084 let mut doc1 = EureDocument::new();
1085 let mut doc2 = EureDocument::new();
1086
1087 let root1 = doc1.get_root_id();
1089 let child1 = doc1
1090 .add_map_child(ObjectKey::String("child".to_string()), root1)
1091 .expect("Failed to add child")
1092 .node_id;
1093 doc1.node_mut(child1).content = NodeValue::Primitive(PrimitiveValue::Bool(true));
1094
1095 let root2 = doc2.get_root_id();
1097 let child2 = doc2
1098 .add_map_child(ObjectKey::String("child".to_string()), root2)
1099 .expect("Failed to add child")
1100 .node_id;
1101 doc2.node_mut(child2).content = NodeValue::Primitive(PrimitiveValue::Bool(true));
1102
1103 assert_eq!(doc1, doc2);
1104 }
1105
1106 #[test]
1107 fn test_partialeq_ignores_node_id_values() {
1108 let mut doc1 = EureDocument::new();
1109 let mut doc2 = EureDocument::new();
1110
1111 let root1 = doc1.get_root_id();
1113 let _intermediate = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1114 let child1 = doc1
1115 .add_map_child(ObjectKey::String("key".to_string()), root1)
1116 .expect("Failed")
1117 .node_id;
1118
1119 let root2 = doc2.get_root_id();
1121 let child2 = doc2
1122 .add_map_child(ObjectKey::String("key".to_string()), root2)
1123 .expect("Failed")
1124 .node_id;
1125
1126 assert_eq!(doc1, doc2);
1129
1130 assert_ne!(child1.0, child2.0);
1132 }
1133
1134 #[test]
1135 fn test_require_map_converts_hole() {
1136 let mut doc = EureDocument::new();
1137 let node_id = doc.create_node(NodeValue::hole());
1138
1139 assert!(doc.node(node_id).content.is_hole());
1140
1141 {
1142 let node = doc.node_mut(node_id);
1143 let _map = node.require_map().expect("Should convert to map");
1144 }
1145
1146 assert!(doc.node(node_id).as_map().is_some());
1147 }
1148
1149 #[test]
1150 fn test_require_array_converts_hole() {
1151 let mut doc = EureDocument::new();
1152 let node_id = doc.create_node(NodeValue::hole());
1153
1154 assert!(doc.node(node_id).content.is_hole());
1155
1156 {
1157 let node = doc.node_mut(node_id);
1158 let _array = node.require_array().expect("Should convert to array");
1159 }
1160
1161 assert!(doc.node(node_id).as_array().is_some());
1162 }
1163
1164 #[test]
1165 fn test_require_tuple_converts_hole() {
1166 let mut doc = EureDocument::new();
1167 let node_id = doc.create_node(NodeValue::hole());
1168
1169 assert!(doc.node(node_id).content.is_hole());
1170
1171 {
1172 let node = doc.node_mut(node_id);
1173 let _tuple = node.require_tuple().expect("Should convert to tuple");
1174 }
1175
1176 assert!(doc.node(node_id).as_tuple().is_some());
1177 }
1178
1179 #[test]
1180 fn test_require_methods_fail_on_wrong_type() {
1181 let mut doc = EureDocument::new();
1182 let primitive_id = doc.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1183
1184 let node = doc.node_mut(primitive_id);
1185 assert_eq!(node.require_map().err(), Some(InsertErrorKind::ExpectedMap));
1186
1187 let node = doc.node_mut(primitive_id);
1188 assert_eq!(
1189 node.require_array().err(),
1190 Some(InsertErrorKind::ExpectedArray)
1191 );
1192
1193 let node = doc.node_mut(primitive_id);
1194 assert_eq!(
1195 node.require_tuple().err(),
1196 Some(InsertErrorKind::ExpectedTuple)
1197 );
1198 }
1199}
1200
1201#[cfg(test)]
1202mod proptests {
1203 extern crate std;
1204
1205 use super::*;
1206 use proptest::prelude::*;
1207 use std::vec::Vec;
1208
1209 fn xid_start_char() -> impl Strategy<Value = char> {
1215 prop_oneof![
1216 prop::char::range('a', 'z'),
1217 prop::char::range('A', 'Z'),
1218 Just('_'),
1219 Just('α'),
1220 Just('日'),
1221 ]
1222 }
1223
1224 fn xid_continue_char() -> impl Strategy<Value = char> {
1226 prop_oneof![
1227 prop::char::range('a', 'z'),
1228 prop::char::range('A', 'Z'),
1229 prop::char::range('0', '9'),
1230 Just('_'),
1231 Just('-'),
1232 Just('α'),
1233 Just('日'),
1234 ]
1235 }
1236
1237 fn arb_identifier() -> impl Strategy<Value = Identifier> {
1239 (
1240 xid_start_char(),
1241 proptest::collection::vec(xid_continue_char(), 0..15),
1242 )
1243 .prop_map(|(first, rest)| {
1244 let mut s = alloc::string::String::with_capacity(1 + rest.len());
1245 s.push(first);
1246 s.extend(rest);
1247 s
1248 })
1249 .prop_filter_map("valid identifier", |s| s.parse::<Identifier>().ok())
1250 }
1251
1252 fn arb_object_key() -> impl Strategy<Value = ObjectKey> {
1254 prop_oneof![
1255 arb_identifier().prop_map(|id| ObjectKey::String(id.to_string())),
1257 (-1000i64..1000).prop_map(|n| ObjectKey::Number(n.into())),
1259 ]
1260 }
1261
1262 fn arb_primitive_value() -> impl Strategy<Value = PrimitiveValue> {
1264 prop_oneof![
1265 Just(PrimitiveValue::Null),
1266 proptest::bool::ANY.prop_map(PrimitiveValue::Bool),
1267 (-1000i64..1000).prop_map(|n| PrimitiveValue::Integer(n.into())),
1268 proptest::num::f64::NORMAL.prop_map(PrimitiveValue::F64),
1269 "[a-zA-Z0-9 ]{0,50}".prop_map(|s| PrimitiveValue::Text(Text::plaintext(s))),
1270 ]
1271 }
1272
1273 proptest! {
1278 #[test]
1281 fn resolve_ident_is_idempotent(ident in arb_identifier()) {
1282 let mut doc = EureDocument::new();
1283 let root_id = doc.get_root_id();
1284
1285 let node_id1 = doc
1286 .resolve_child_by_segment(PathSegment::Ident(ident.clone()), root_id)
1287 .expect("First resolve failed")
1288 .node_id;
1289
1290 let node_id2 = doc
1291 .resolve_child_by_segment(PathSegment::Ident(ident), root_id)
1292 .expect("Second resolve failed")
1293 .node_id;
1294
1295 prop_assert_eq!(node_id1, node_id2, "Ident resolution should be idempotent");
1296 }
1297
1298 #[test]
1300 fn resolve_value_is_idempotent(key in arb_object_key()) {
1301 let mut doc = EureDocument::new();
1302 let root_id = doc.get_root_id();
1303
1304 let node_id1 = doc
1305 .resolve_child_by_segment(PathSegment::Value(key.clone()), root_id)
1306 .expect("First resolve failed")
1307 .node_id;
1308
1309 let node_id2 = doc
1310 .resolve_child_by_segment(PathSegment::Value(key), root_id)
1311 .expect("Second resolve failed")
1312 .node_id;
1313
1314 prop_assert_eq!(node_id1, node_id2, "Value resolution should be idempotent");
1315 }
1316
1317 #[test]
1319 fn resolve_extension_is_idempotent(ident in arb_identifier()) {
1320 let mut doc = EureDocument::new();
1321 let root_id = doc.get_root_id();
1322
1323 let node_id1 = doc
1324 .resolve_child_by_segment(PathSegment::Extension(ident.clone()), root_id)
1325 .expect("First resolve failed")
1326 .node_id;
1327
1328 let node_id2 = doc
1329 .resolve_child_by_segment(PathSegment::Extension(ident), root_id)
1330 .expect("Second resolve failed")
1331 .node_id;
1332
1333 prop_assert_eq!(node_id1, node_id2, "Extension resolution should be idempotent");
1334 }
1335
1336 #[test]
1338 fn resolve_tuple_index_is_idempotent(index in 0u8..10) {
1339 let mut doc = EureDocument::new();
1340 let parent_id = doc.create_node_uninitialized();
1341
1342 for i in 0..index {
1344 doc.add_tuple_element(i, parent_id).expect("Sequential add failed");
1345 }
1346
1347 let node_id1 = doc
1349 .resolve_child_by_segment(PathSegment::TupleIndex(index), parent_id)
1350 .expect("First resolve failed")
1351 .node_id;
1352
1353 let node_id2 = doc
1354 .resolve_child_by_segment(PathSegment::TupleIndex(index), parent_id)
1355 .expect("Second resolve failed")
1356 .node_id;
1357
1358 prop_assert_eq!(node_id1, node_id2, "TupleIndex resolution should be idempotent");
1359 }
1360
1361 #[test]
1363 fn resolve_array_index_some_is_idempotent(index in 0usize..10) {
1364 let mut doc = EureDocument::new();
1365 let parent_id = doc.create_node_uninitialized();
1366
1367 for i in 0..index {
1369 doc.add_array_element(Some(i), parent_id).expect("Sequential add failed");
1370 }
1371
1372 let node_id1 = doc
1374 .resolve_child_by_segment(PathSegment::ArrayIndex(Some(index)), parent_id)
1375 .expect("First resolve failed")
1376 .node_id;
1377
1378 let node_id2 = doc
1379 .resolve_child_by_segment(PathSegment::ArrayIndex(Some(index)), parent_id)
1380 .expect("Second resolve failed")
1381 .node_id;
1382
1383 prop_assert_eq!(node_id1, node_id2, "ArrayIndex(Some) resolution should be idempotent");
1384 }
1385
1386 #[test]
1388 fn resolve_array_index_none_always_creates_new(count in 1usize..10) {
1389 let mut doc = EureDocument::new();
1390 let parent_id = doc.create_node_uninitialized();
1391
1392 let mut node_ids = Vec::new();
1393 for _ in 0..count {
1394 let node_id = doc
1395 .resolve_child_by_segment(PathSegment::ArrayIndex(None), parent_id)
1396 .expect("Resolve failed")
1397 .node_id;
1398 node_ids.push(node_id);
1399 }
1400
1401 for i in 0..node_ids.len() {
1403 for j in (i+1)..node_ids.len() {
1404 prop_assert_ne!(node_ids[i], node_ids[j],
1405 "ArrayIndex(None) should create unique nodes");
1406 }
1407 }
1408
1409 let array = doc.node(parent_id).as_array().expect("Expected array");
1411 prop_assert_eq!(array.len(), count, "Array length should match push count");
1412 }
1413
1414 #[test]
1416 fn resolve_array_index_on_map_fails(index in 0usize..10) {
1417 let mut doc = EureDocument::new();
1418 let root_id = doc.get_root_id(); doc.node_mut(root_id).content = NodeValue::empty_map();
1422
1423 let result = doc.resolve_child_by_segment(PathSegment::ArrayIndex(Some(index)), root_id);
1424 prop_assert!(result.is_err(), "ArrayIndex on map should fail");
1425 prop_assert_eq!(result.err(), Some(InsertErrorKind::ExpectedArray));
1426 }
1427
1428 #[test]
1430 fn resolve_tuple_index_on_array_fails(index in 0u8..10) {
1431 let mut doc = EureDocument::new();
1432 let parent_id = doc.create_node(NodeValue::empty_array());
1433
1434 let result = doc.resolve_child_by_segment(PathSegment::TupleIndex(index), parent_id);
1435 prop_assert!(result.is_err(), "TupleIndex on array should fail");
1436 prop_assert_eq!(result.err(), Some(InsertErrorKind::ExpectedTuple));
1437 }
1438
1439 #[test]
1441 fn resolve_array_index_on_primitive_fails(value in arb_primitive_value()) {
1442 let mut doc = EureDocument::new();
1443 let node_id = doc.create_node(NodeValue::Primitive(value));
1444
1445 let result = doc.resolve_child_by_segment(PathSegment::ArrayIndex(Some(0)), node_id);
1446 prop_assert!(result.is_err(), "ArrayIndex on primitive should fail");
1447 prop_assert_eq!(result.err(), Some(InsertErrorKind::ExpectedArray));
1448 }
1449
1450 #[test]
1452 fn resolve_array_index_non_sequential_fails(skip in 1usize..10) {
1453 let mut doc = EureDocument::new();
1454 let parent_id = doc.create_node(NodeValue::empty_array());
1455
1456 let result = doc.resolve_child_by_segment(PathSegment::ArrayIndex(Some(skip)), parent_id);
1458 prop_assert!(result.is_err(), "Non-sequential ArrayIndex should fail");
1459
1460 match result.err() {
1461 Some(InsertErrorKind::ArrayIndexInvalid { index, expected_index }) => {
1462 prop_assert_eq!(index, skip);
1463 prop_assert_eq!(expected_index, 0);
1464 }
1465 other => prop_assert!(false, "Expected ArrayIndexInvalid, got {:?}", other),
1466 }
1467 }
1468
1469 #[test]
1471 fn resolve_tuple_index_non_sequential_fails(skip in 1u8..10) {
1472 let mut doc = EureDocument::new();
1473 let parent_id = doc.create_node(NodeValue::empty_tuple());
1474
1475 let result = doc.resolve_child_by_segment(PathSegment::TupleIndex(skip), parent_id);
1476 prop_assert!(result.is_err(), "Non-sequential TupleIndex should fail");
1477
1478 match result.err() {
1479 Some(InsertErrorKind::TupleIndexInvalid { index, expected_index }) => {
1480 prop_assert_eq!(index, skip);
1481 prop_assert_eq!(expected_index, 0);
1482 }
1483 other => prop_assert!(false, "Expected TupleIndexInvalid, got {:?}", other),
1484 }
1485 }
1486 }
1487
1488 proptest! {
1493 #[test]
1495 fn multiple_different_extensions_allowed(
1496 ext1 in arb_identifier(),
1497 ext2 in arb_identifier(),
1498 ) {
1499 prop_assume!(ext1 != ext2);
1500
1501 let mut doc = EureDocument::new();
1502 let root_id = doc.get_root_id();
1503
1504 let node_id1 = doc.add_extension(ext1.clone(), root_id)
1505 .expect("First extension failed")
1506 .node_id;
1507 let node_id2 = doc.add_extension(ext2.clone(), root_id)
1508 .expect("Second extension failed")
1509 .node_id;
1510
1511 let node = doc.node(root_id);
1512 prop_assert_eq!(node.extensions.get(&ext1), Some(&node_id1));
1513 prop_assert_eq!(node.extensions.get(&ext2), Some(&node_id2));
1514 }
1515
1516 #[test]
1518 fn duplicate_extension_fails(ext in arb_identifier()) {
1519 let mut doc = EureDocument::new();
1520 let root_id = doc.get_root_id();
1521
1522 let _first = doc.add_extension(ext.clone(), root_id)
1523 .expect("First extension should succeed");
1524
1525 let result = doc.add_extension(ext.clone(), root_id);
1526 prop_assert_eq!(
1527 result.err(),
1528 Some(InsertErrorKind::AlreadyAssignedExtension { identifier: ext }),
1529 "Duplicate extension should fail"
1530 );
1531 }
1532 }
1533
1534 proptest! {
1539 #[test]
1541 fn document_equality_ignores_node_ids(
1542 keys in proptest::collection::vec(arb_object_key(), 1..5)
1543 .prop_filter("unique keys", |keys| {
1544 let unique: std::collections::HashSet<_> = keys.iter().collect();
1545 unique.len() == keys.len()
1546 }),
1547 ) {
1548 let mut doc1 = EureDocument::new();
1549 let mut doc2 = EureDocument::new();
1550
1551 let _ = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1553
1554 let root1 = doc1.get_root_id();
1555 let root2 = doc2.get_root_id();
1556
1557 for key in &keys {
1559 doc1.add_map_child(key.clone(), root1).expect("Add failed");
1560 doc2.add_map_child(key.clone(), root2).expect("Add failed");
1561 }
1562
1563 prop_assert_eq!(doc1, doc2, "Documents with same structure should be equal");
1564 }
1565
1566 #[test]
1568 fn document_equality_reflexive(
1569 keys in proptest::collection::vec(arb_object_key(), 0..5)
1570 .prop_filter("unique keys", |keys| {
1571 let unique: std::collections::HashSet<_> = keys.iter().collect();
1572 unique.len() == keys.len()
1573 }),
1574 ) {
1575 let mut doc = EureDocument::new();
1576 let root_id = doc.get_root_id();
1577
1578 for key in &keys {
1579 doc.add_map_child(key.clone(), root_id).expect("Add failed");
1580 }
1581
1582 prop_assert_eq!(&doc, &doc, "Document should equal itself");
1583 }
1584
1585 #[test]
1587 fn document_equality_different_content(
1588 key1 in arb_object_key(),
1589 key2 in arb_object_key(),
1590 ) {
1591 prop_assume!(key1 != key2);
1592
1593 let mut doc1 = EureDocument::new();
1594 let mut doc2 = EureDocument::new();
1595
1596 let root1 = doc1.get_root_id();
1597 let root2 = doc2.get_root_id();
1598
1599 doc1.add_map_child(key1, root1).expect("Add failed");
1600 doc2.add_map_child(key2, root2).expect("Add failed");
1601
1602 prop_assert_ne!(doc1, doc2, "Documents with different keys should not be equal");
1603 }
1604
1605 #[test]
1607 fn document_equality_for_arrays(count in 1usize..10) {
1608 let mut doc1 = EureDocument::new();
1609 let mut doc2 = EureDocument::new();
1610
1611 let _ = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1613
1614 let root1 = doc1.get_root_id();
1615 let root2 = doc2.get_root_id();
1616
1617 doc1.node_mut(root1).content = NodeValue::empty_array();
1619 doc2.node_mut(root2).content = NodeValue::empty_array();
1620
1621 for _ in 0..count {
1622 doc1.add_array_element(None, root1).expect("Add failed");
1623 doc2.add_array_element(None, root2).expect("Add failed");
1624 }
1625
1626 prop_assert_eq!(doc1, doc2, "Documents with same array structure should be equal");
1627 }
1628
1629 #[test]
1631 fn document_equality_for_tuples(count in 1u8..10) {
1632 let mut doc1 = EureDocument::new();
1633 let mut doc2 = EureDocument::new();
1634
1635 let _ = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1636
1637 let root1 = doc1.get_root_id();
1638 let root2 = doc2.get_root_id();
1639
1640 doc1.node_mut(root1).content = NodeValue::empty_tuple();
1641 doc2.node_mut(root2).content = NodeValue::empty_tuple();
1642
1643 for i in 0..count {
1644 doc1.add_tuple_element(i, root1).expect("Add failed");
1645 doc2.add_tuple_element(i, root2).expect("Add failed");
1646 }
1647
1648 prop_assert_eq!(doc1, doc2, "Documents with same tuple structure should be equal");
1649 }
1650
1651 #[test]
1653 fn document_equality_for_primitives(value in arb_primitive_value()) {
1654 let mut doc1 = EureDocument::new();
1655 let mut doc2 = EureDocument::new();
1656
1657 let _ = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1658
1659 let root1 = doc1.get_root_id();
1660 let root2 = doc2.get_root_id();
1661
1662 doc1.node_mut(root1).content = NodeValue::Primitive(value.clone());
1663 doc2.node_mut(root2).content = NodeValue::Primitive(value);
1664
1665 prop_assert_eq!(doc1, doc2, "Documents with same primitive value should be equal");
1666 }
1667
1668 #[test]
1670 fn document_equality_considers_extensions(
1671 ext_name in arb_identifier(),
1672 value in arb_primitive_value(),
1673 ) {
1674 let mut doc1 = EureDocument::new();
1675 let mut doc2 = EureDocument::new();
1676
1677 let _ = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1678
1679 let root1 = doc1.get_root_id();
1680 let root2 = doc2.get_root_id();
1681
1682 let ext1_id = doc1.add_extension(ext_name.clone(), root1).expect("Add ext failed").node_id;
1684 let ext2_id = doc2.add_extension(ext_name.clone(), root2).expect("Add ext failed").node_id;
1685
1686 doc1.node_mut(ext1_id).content = NodeValue::Primitive(value.clone());
1688 doc2.node_mut(ext2_id).content = NodeValue::Primitive(value);
1689
1690 prop_assert_eq!(doc1, doc2, "Documents with same extensions should be equal");
1691 }
1692
1693 #[test]
1695 fn document_equality_different_extensions(
1696 ext1 in arb_identifier(),
1697 ext2 in arb_identifier(),
1698 ) {
1699 prop_assume!(ext1 != ext2);
1700
1701 let mut doc1 = EureDocument::new();
1702 let mut doc2 = EureDocument::new();
1703
1704 let root1 = doc1.get_root_id();
1705 let root2 = doc2.get_root_id();
1706
1707 doc1.add_extension(ext1, root1).expect("Add ext failed");
1708 doc2.add_extension(ext2, root2).expect("Add ext failed");
1709
1710 prop_assert_ne!(doc1, doc2, "Documents with different extensions should not be equal");
1711 }
1712 }
1713
1714 proptest! {
1719 #[test]
1721 fn copy_subtree_preserves_primitive(value in arb_primitive_value()) {
1722 let mut src = EureDocument::new();
1723 let src_id = src.create_node(NodeValue::Primitive(value.clone()));
1724
1725 let dst = src.node_subtree_to_document(src_id);
1726
1727 let dst_node = dst.root();
1728 match &dst_node.content {
1729 NodeValue::Primitive(copied_value) => {
1730 prop_assert_eq!(copied_value, &value, "Primitive value should be preserved");
1731 }
1732 other => {
1733 prop_assert!(false, "Expected Primitive, got {:?}", other);
1734 }
1735 }
1736 }
1737
1738 #[test]
1741 fn copy_subtree_array_has_valid_node_ids(count in 1usize..10) {
1742 let mut src = EureDocument::new();
1743 let array_id = src.create_node(NodeValue::empty_array());
1744
1745 for _ in 0..count {
1746 src.add_array_element(None, array_id).expect("Add failed");
1747 }
1748
1749 let dst = src.node_subtree_to_document(array_id);
1750
1751 let dst_array = dst.root().as_array().expect("Expected array");
1753 prop_assert_eq!(dst_array.len(), count, "Copied array should have correct length");
1754
1755 for i in 0..dst_array.len() {
1757 let child_id = dst_array.get(i).expect("Should have element");
1758 prop_assert!(
1759 dst.get_node(child_id).is_some(),
1760 "NodeId {:?} at index {} must exist in destination", child_id, i
1761 );
1762 }
1763 }
1764
1765 #[test]
1767 fn copy_subtree_map_has_valid_node_ids(
1768 keys in proptest::collection::vec(arb_object_key(), 1..5)
1769 .prop_filter("unique keys", |keys| {
1770 let unique: std::collections::HashSet<_> = keys.iter().collect();
1771 unique.len() == keys.len()
1772 }),
1773 ) {
1774 let mut src = EureDocument::new();
1775 let map_id = src.create_node(NodeValue::empty_map());
1776
1777 for key in &keys {
1778 src.add_map_child(key.clone(), map_id).expect("Add failed");
1779 }
1780
1781 let dst = src.node_subtree_to_document(map_id);
1782
1783 let dst_map = dst.root().as_map().expect("Expected map");
1784 prop_assert_eq!(dst_map.len(), keys.len(), "Copied map should have correct size");
1785
1786 for (key, &child_id) in dst_map.iter() {
1788 prop_assert!(
1789 dst.get_node(child_id).is_some(),
1790 "NodeId {:?} for key {:?} must exist in destination", child_id, key
1791 );
1792 }
1793 }
1794
1795 #[test]
1797 fn copy_subtree_tuple_has_valid_node_ids(count in 1u8..10) {
1798 let mut src = EureDocument::new();
1799 let tuple_id = src.create_node(NodeValue::empty_tuple());
1800
1801 for i in 0..count {
1802 src.add_tuple_element(i, tuple_id).expect("Add failed");
1803 }
1804
1805 let dst = src.node_subtree_to_document(tuple_id);
1806
1807 let dst_tuple = dst.root().as_tuple().expect("Expected tuple");
1808 prop_assert_eq!(dst_tuple.len(), count as usize, "Copied tuple should have correct length");
1809
1810 for i in 0..dst_tuple.len() {
1812 let child_id = dst_tuple.get(i).expect("Should have element");
1813 prop_assert!(
1814 dst.get_node(child_id).is_some(),
1815 "NodeId {:?} at index {} must exist in destination", child_id, i
1816 );
1817 }
1818 }
1819
1820 #[test]
1822 fn copy_subtree_preserves_nested_mixed_content(
1823 key in arb_object_key(),
1824 value in arb_primitive_value(),
1825 ) {
1826 let mut src = EureDocument::new();
1827 let map_id = src.create_node(NodeValue::empty_map());
1828
1829 let child_id = src.add_map_child(key.clone(), map_id).expect("Add failed").node_id;
1831 src.node_mut(child_id).content = NodeValue::empty_array();
1832 let elem_id = src.add_array_element(None, child_id).expect("Add failed").node_id;
1833 src.node_mut(elem_id).content = NodeValue::Primitive(value.clone());
1834
1835 let dst = src.node_subtree_to_document(map_id);
1836
1837 let dst_map = dst.root().as_map().expect("Expected map");
1839 let dst_child_id = dst_map.get(&key).expect("Should have key");
1840 let dst_child = dst.get_node(*dst_child_id).expect("Child should exist");
1841 let dst_array = dst_child.as_array().expect("Expected array");
1842 prop_assert_eq!(dst_array.len(), 1);
1843
1844 let dst_elem_id = dst_array.get(0).expect("Should have element");
1845 let dst_elem = dst.get_node(dst_elem_id).expect("Element should exist");
1846 prop_assert_eq!(
1847 &dst_elem.content,
1848 &NodeValue::Primitive(value),
1849 "Primitive value should be preserved in nested structure"
1850 );
1851 }
1852
1853 #[test]
1855 fn copy_subtree_preserves_extensions(
1856 ext_name in arb_identifier(),
1857 ext_value in arb_primitive_value(),
1858 ) {
1859 let mut src = EureDocument::new();
1860 let node_id = src.create_node(NodeValue::empty_map());
1861
1862 let ext_id = src.add_extension(ext_name.clone(), node_id).expect("Add ext failed").node_id;
1864 src.node_mut(ext_id).content = NodeValue::Primitive(ext_value.clone());
1865
1866 let dst = src.node_subtree_to_document(node_id);
1867
1868 let dst_ext = dst.root().extensions.get(&ext_name);
1870 prop_assert!(dst_ext.is_some(), "Extension should be copied");
1871
1872 let dst_ext_id = *dst_ext.unwrap();
1873 let dst_ext_node = dst.get_node(dst_ext_id).expect("Extension node should exist");
1874 prop_assert_eq!(
1875 &dst_ext_node.content,
1876 &NodeValue::Primitive(ext_value),
1877 "Extension value should be preserved"
1878 );
1879 }
1880
1881 #[test]
1883 fn copy_subtree_preserves_nested_extensions(
1884 key in arb_object_key(),
1885 ext_name in arb_identifier(),
1886 ) {
1887 let mut src = EureDocument::new();
1888 let map_id = src.create_node(NodeValue::empty_map());
1889
1890 let child_id = src.add_map_child(key.clone(), map_id).expect("Add failed").node_id;
1892 src.add_extension(ext_name.clone(), child_id).expect("Add ext failed");
1894
1895 let dst = src.node_subtree_to_document(map_id);
1896
1897 let dst_map = dst.root().as_map().expect("Expected map");
1899 let dst_child_id = dst_map.get(&key).expect("Should have key");
1900 let dst_child = dst.get_node(*dst_child_id).expect("Child should exist");
1901
1902 prop_assert!(
1903 dst_child.extensions.contains_key(&ext_name),
1904 "Extension on nested node should be preserved"
1905 );
1906 }
1907 }
1908
1909 proptest! {
1914 #[test]
1916 fn map_key_uniqueness(key in arb_object_key()) {
1917 let mut doc = EureDocument::new();
1918 let root_id = doc.get_root_id();
1919
1920 let _first = doc.add_map_child(key.clone(), root_id)
1921 .expect("First add should succeed");
1922
1923 let result = doc.add_map_child(key.clone(), root_id);
1924 prop_assert_eq!(
1925 result.err(),
1926 Some(InsertErrorKind::AlreadyAssigned { key }),
1927 "Duplicate map key should fail"
1928 );
1929 }
1930
1931 #[test]
1933 fn multiple_map_keys_allowed(
1934 keys in proptest::collection::vec(arb_object_key(), 2..10)
1935 .prop_filter("unique keys", |keys| {
1936 let unique: std::collections::HashSet<_> = keys.iter().collect();
1937 unique.len() == keys.len()
1938 })
1939 ) {
1940 let mut doc = EureDocument::new();
1941 let root_id = doc.get_root_id();
1942
1943 for key in &keys {
1944 doc.add_map_child(key.clone(), root_id).expect("Add should succeed");
1945 }
1946
1947 let map = doc.node(root_id).as_map().expect("Expected map");
1948 prop_assert_eq!(map.len(), keys.len(), "All unique keys should be present");
1949 }
1950 }
1951
1952 proptest! {
1957 #[test]
1959 fn created_nodes_are_accessible(count in 1usize..20) {
1960 let mut doc = EureDocument::new();
1961 let mut node_ids = Vec::new();
1962
1963 for _ in 0..count {
1964 let id = doc.create_node_uninitialized();
1965 node_ids.push(id);
1966 }
1967
1968 for id in node_ids {
1969 prop_assert!(doc.get_node(id).is_some(),
1970 "Created node {:?} should be accessible", id);
1971 }
1972 }
1973
1974 #[test]
1976 fn invalid_node_ids_return_none(count in 1usize..10) {
1977 let mut doc = EureDocument::new();
1978
1979 for _ in 0..count {
1980 doc.create_node_uninitialized();
1981 }
1982
1983 let invalid_id = NodeId(count + 100);
1985 prop_assert!(doc.get_node(invalid_id).is_none(),
1986 "Invalid NodeId should return None");
1987 }
1988
1989 #[test]
1991 fn root_is_always_accessible(count in 0usize..10) {
1992 let mut doc = EureDocument::new();
1993
1994 for _ in 0..count {
1996 doc.create_node_uninitialized();
1997 }
1998
1999 let root_id = doc.get_root_id();
2000 prop_assert!(doc.get_node(root_id).is_some(), "Root should always be accessible");
2001 prop_assert_eq!(root_id, NodeId(0), "Root should be NodeId(0)");
2002 }
2003 }
2004
2005 proptest! {
2010 #[test]
2012 fn nested_structures_are_equal(
2013 keys in proptest::collection::vec(arb_object_key(), 1..3),
2014 depth in 1usize..4,
2015 ) {
2016 let mut doc1 = EureDocument::new();
2017 let mut doc2 = EureDocument::new();
2018
2019 fn build_nested(
2020 doc: &mut EureDocument,
2021 parent_id: NodeId,
2022 keys: &[ObjectKey],
2023 depth: usize,
2024 ) {
2025 if depth == 0 {
2026 return;
2027 }
2028 let child_ids: Vec<NodeId> = keys
2030 .iter()
2031 .filter_map(|key| {
2032 doc.add_map_child(key.clone(), parent_id).ok().map(|c| c.node_id)
2033 })
2034 .collect();
2035
2036 for child_id in child_ids {
2038 build_nested(doc, child_id, keys, depth - 1);
2039 }
2040 }
2041
2042 let root1 = doc1.get_root_id();
2043 let root2 = doc2.get_root_id();
2044
2045 build_nested(&mut doc1, root1, &keys, depth);
2046 build_nested(&mut doc2, root2, &keys, depth);
2047
2048 prop_assert_eq!(doc1, doc2, "Nested structures should be equal");
2049 }
2050 }
2051}