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