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