Skip to main content

eure_document/
document.rs

1pub mod constructor;
2pub mod interpreter_sink;
3pub mod node;
4pub mod source_constructor;
5
6use crate::document::node::{NodeArray, NodeTuple};
7use crate::prelude_internal::*;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct NodeId(pub usize);
11
12#[derive(Debug, Clone)]
13pub struct EureDocument {
14    pub(crate) root: NodeId,
15    nodes: Vec<Node>,
16}
17
18#[derive(Debug, PartialEq, thiserror::Error, Clone)]
19#[error("Insert error: {kind} at {path}")]
20pub struct InsertError {
21    pub kind: InsertErrorKind,
22    pub path: EurePath,
23}
24
25#[derive(Debug, PartialEq, thiserror::Error, Clone)]
26pub enum InsertErrorKind {
27    #[error("Already assigned")]
28    AlreadyAssigned { key: ObjectKey },
29    #[error("Extension already assigned: {identifier}")]
30    AlreadyAssignedExtension { identifier: Identifier },
31    #[error("Expected array")]
32    ExpectedArray,
33    #[error("Array index invalid: expected {expected_index} but got {index}")]
34    ArrayIndexInvalid { index: usize, expected_index: usize },
35    #[error("Expected map")]
36    ExpectedMap,
37    #[error("Expected tuple")]
38    ExpectedTuple,
39    #[error("Tuple index invalid: expected {expected_index} but got {index}")]
40    TupleIndexInvalid { index: u8, expected_index: usize },
41    #[error("Binding target already has a value")]
42    BindingTargetHasValue,
43    #[error("Scope error: {0}")]
44    ScopeError(#[from] constructor::ScopeError),
45    #[error("Constructor error: {0}")]
46    ConstructorError(#[from] ConstructorError),
47}
48
49/// Protocol errors for SourceConstructor operations.
50#[derive(Debug, PartialEq, thiserror::Error, Clone)]
51pub enum ConstructorError {
52    #[error("set_block_value called without a preceding bind operation")]
53    MissingBindBeforeSetBlockValue,
54    #[error("end_binding_value called without a preceding bind operation")]
55    MissingBindBeforeEndBindingValue,
56    #[error("end_binding_block called without a preceding end_eure_block")]
57    MissingEndEureBlockBeforeEndBindingBlock,
58    #[error("end_section_block called without a preceding end_eure_block")]
59    MissingEndEureBlockBeforeEndSectionBlock,
60    #[error("end_eure_block called but builder stack is not in EureBlock state")]
61    InvalidBuilderStackForEndEureBlock,
62    #[error("end_section_items called but builder stack is not in SectionItems state")]
63    InvalidBuilderStackForEndSectionItems,
64    #[error("ArrayIndex must follow a key segment; standalone [] is not valid")]
65    StandaloneArrayIndex,
66}
67
68impl Default for EureDocument {
69    fn default() -> Self {
70        Self::new()
71    }
72}
73
74impl PartialEq for EureDocument {
75    fn eq(&self, other: &Self) -> bool {
76        self.nodes_equal(self.root, other, other.root)
77    }
78}
79
80impl EureDocument {
81    /// Compare two nodes structurally, ignoring NodeId values
82    fn nodes_equal(&self, id1: NodeId, other: &EureDocument, id2: NodeId) -> bool {
83        let node1 = &self.nodes[id1.0];
84        let node2 = &other.nodes[id2.0];
85
86        // Compare extensions
87        if node1.extensions.len() != node2.extensions.len() {
88            return false;
89        }
90
91        for (key1, &child_id1) in &node1.extensions {
92            match node2.extensions.get(key1) {
93                Some(&child_id2) => {
94                    if !self.nodes_equal(child_id1, other, child_id2) {
95                        return false;
96                    }
97                }
98                None => return false,
99            }
100        }
101
102        // Compare content
103        self.node_values_equal(&node1.content, other, &node2.content)
104    }
105
106    /// Compare two NodeValues structurally
107    fn node_values_equal(
108        &self,
109        value1: &NodeValue,
110        other: &EureDocument,
111        value2: &NodeValue,
112    ) -> bool {
113        match (value1, value2) {
114            (NodeValue::Hole(l1), NodeValue::Hole(l2)) => l1 == l2,
115            (NodeValue::Primitive(p1), NodeValue::Primitive(p2)) => p1 == p2,
116            (NodeValue::Array(arr1), NodeValue::Array(arr2)) => {
117                self.node_arrays_equal(arr1, other, arr2)
118            }
119            (NodeValue::Tuple(tup1), NodeValue::Tuple(tup2)) => {
120                self.node_tuples_equal(tup1, other, tup2)
121            }
122            (NodeValue::Map(map1), NodeValue::Map(map2)) => self.node_maps_equal(map1, other, map2),
123            _ => false,
124        }
125    }
126
127    fn node_arrays_equal(&self, arr1: &NodeArray, other: &EureDocument, arr2: &NodeArray) -> bool {
128        if arr1.len() != arr2.len() {
129            return false;
130        }
131
132        for (child_id1, child_id2) in arr1.iter().zip(arr2.iter()) {
133            if !self.nodes_equal(*child_id1, other, *child_id2) {
134                return false;
135            }
136        }
137
138        true
139    }
140
141    fn node_tuples_equal(&self, tup1: &NodeTuple, other: &EureDocument, tup2: &NodeTuple) -> bool {
142        if tup1.len() != tup2.len() {
143            return false;
144        }
145
146        for (child_id1, child_id2) in tup1.iter().zip(tup2.iter()) {
147            if !self.nodes_equal(*child_id1, other, *child_id2) {
148                return false;
149            }
150        }
151
152        true
153    }
154
155    fn node_maps_equal(&self, map1: &NodeMap, other: &EureDocument, map2: &NodeMap) -> bool {
156        if map1.len() != map2.len() {
157            return false;
158        }
159
160        for (key1, &child_id1) in map1.iter() {
161            match map2.get(key1) {
162                Some(&child_id2) => {
163                    if !self.nodes_equal(child_id1, other, child_id2) {
164                        return false;
165                    }
166                }
167                None => return false,
168            }
169        }
170
171        true
172    }
173
174    pub fn new() -> Self {
175        Self {
176            root: NodeId(0),
177            nodes: vec![Node {
178                content: NodeValue::hole(),
179                extensions: Map::new(),
180            }],
181        }
182    }
183
184    pub fn new_empty() -> Self {
185        Self {
186            root: NodeId(0),
187            nodes: vec![Node {
188                content: NodeValue::Map(Default::default()),
189                extensions: Map::new(),
190            }],
191        }
192    }
193
194    pub fn new_primitive(value: PrimitiveValue) -> Self {
195        Self {
196            root: NodeId(0),
197            nodes: vec![Node {
198                content: NodeValue::Primitive(value),
199                extensions: Map::new(),
200            }],
201        }
202    }
203
204    pub fn root(&self) -> &Node {
205        &self.nodes[self.root.0]
206    }
207
208    pub fn get_root_id(&self) -> NodeId {
209        self.root
210    }
211
212    pub fn node(&self, id: NodeId) -> &Node {
213        &self.nodes[id.0]
214    }
215
216    pub fn get_node(&self, id: NodeId) -> Option<&Node> {
217        self.nodes.get(id.0)
218    }
219
220    pub fn node_mut(&mut self, id: NodeId) -> &mut Node {
221        &mut self.nodes[id.0]
222    }
223
224    pub fn get_node_mut(&mut self, id: NodeId) -> Option<&mut Node> {
225        self.nodes.get_mut(id.0)
226    }
227
228    pub fn create_node(&mut self, new: NodeValue) -> NodeId {
229        self.nodes.push(Node {
230            content: new,
231            extensions: Map::new(),
232        });
233        NodeId(self.nodes.len() - 1)
234    }
235
236    pub fn create_node_uninitialized(&mut self) -> NodeId {
237        self.create_node(NodeValue::hole())
238    }
239
240    /// Set the content of a node directly
241    pub fn set_content(&mut self, node_id: NodeId, content: NodeValue) {
242        self.nodes[node_id.0].content = content;
243    }
244
245    pub fn add_child_by_segment(
246        &mut self,
247        segment: PathSegment,
248        parent_node_id: NodeId,
249    ) -> Result<NodeMut<'_>, InsertErrorKind> {
250        match segment {
251            PathSegment::Ident(identifier) => {
252                self.add_map_child(ObjectKey::String(identifier.into_string()), parent_node_id)
253            }
254            PathSegment::Value(object_key) => self.add_map_child(object_key, parent_node_id),
255            PathSegment::Extension(identifier) => self.add_extension(identifier, parent_node_id),
256            PathSegment::TupleIndex(index) => self.add_tuple_element(index, parent_node_id),
257            PathSegment::ArrayIndex(index) => self.add_array_element(index, parent_node_id),
258        }
259    }
260
261    pub fn add_map_child(
262        &mut self,
263        object_key: ObjectKey,
264        parent_node_id: NodeId,
265    ) -> Result<NodeMut<'_>, InsertErrorKind> {
266        let node_id = self.create_node_uninitialized();
267        let node = self.node_mut(parent_node_id);
268        let map = node.require_map()?;
269        map.add(object_key, node_id)?;
270        Ok(NodeMut::new(self, node_id))
271    }
272
273    pub fn add_extension(
274        &mut self,
275        identifier: Identifier,
276        parent_node_id: NodeId,
277    ) -> Result<NodeMut<'_>, InsertErrorKind> {
278        let node_id = self.create_node_uninitialized();
279        let node = self.node_mut(parent_node_id);
280        if node.extensions.contains_key(&identifier) {
281            return Err(InsertErrorKind::AlreadyAssignedExtension { identifier });
282        }
283        node.extensions.insert(identifier, node_id);
284        Ok(NodeMut::new(self, node_id))
285    }
286
287    pub fn add_tuple_element(
288        &mut self,
289        index: u8,
290        parent_node_id: NodeId,
291    ) -> Result<NodeMut<'_>, InsertErrorKind> {
292        let node_id = self.create_node_uninitialized();
293        let node = self.node_mut(parent_node_id);
294        let tuple = node.require_tuple()?;
295        tuple.add_at(index, node_id)?;
296        Ok(NodeMut::new(self, node_id))
297    }
298
299    pub fn add_array_element(
300        &mut self,
301        index: Option<usize>,
302        parent_node_id: NodeId,
303    ) -> Result<NodeMut<'_>, InsertErrorKind> {
304        let node_id = self.create_node_uninitialized();
305        let node = self.node_mut(parent_node_id);
306        let array = node.require_array()?;
307        if let Some(index) = index {
308            array.add_at(index, node_id)?;
309        } else {
310            array.push(node_id)?;
311        }
312        Ok(NodeMut::new(self, node_id))
313    }
314
315    /// Resolves a path segment to a node ID, creating if necessary.
316    ///
317    /// This operation is idempotent for most segments, reusing existing nodes.
318    /// Exception: `ArrayIndex(None)` always creates a new array element (push operation).
319    pub fn resolve_child_by_segment(
320        &mut self,
321        segment: PathSegment,
322        parent_node_id: NodeId,
323    ) -> Result<NodeMut<'_>, InsertErrorKind> {
324        // 既存のノードを探す
325        let node = self.node(parent_node_id);
326
327        let existing = match &segment {
328            PathSegment::Ident(identifier) => node
329                .as_map()
330                .and_then(|m| m.get(&ObjectKey::String(identifier.clone().into_string())))
331                .copied(),
332            PathSegment::Value(object_key) => {
333                node.as_map().and_then(|m| m.get(object_key)).copied()
334            }
335            PathSegment::Extension(identifier) => node.get_extension(identifier),
336            PathSegment::TupleIndex(index) => node.as_tuple().and_then(|t| t.get(*index as usize)),
337            PathSegment::ArrayIndex(Some(index)) => node.as_array().and_then(|a| a.get(*index)),
338            PathSegment::ArrayIndex(None) => None, // push always creates new
339        };
340
341        // 既存ノードがあればそれを返す
342        if let Some(node_id) = existing {
343            return Ok(NodeMut::new(self, node_id));
344        }
345
346        // なければ作成
347        self.add_child_by_segment(segment, parent_node_id)
348    }
349
350    /// Convert a subtree of a document to a standalone document.
351    pub fn node_subtree_to_document(&self, node_id: NodeId) -> EureDocument {
352        let mut result = EureDocument::new();
353        let root_id = result.get_root_id();
354        self.copy_subtree(node_id, &mut result, root_id);
355        result
356    }
357
358    pub fn copy_subtree(&self, src_id: NodeId, dst: &mut EureDocument, dst_id: NodeId) {
359        let src_node = self.node(src_id);
360        dst.node_mut(dst_id).content = src_node.content.clone();
361
362        // Skip ALL extensions during literal comparison.
363        // Extensions are schema metadata (like $variant, $deny-untagged, $optional, etc.)
364        // and should not be part of the literal value comparison.
365        // Literal types compare only the data structure, not metadata.
366
367        // Copy children based on content type
368        match &src_node.content {
369            NodeValue::Array(arr) => {
370                for &child_src_id in arr.iter() {
371                    if let Ok(result) = dst.add_array_element(None, dst_id) {
372                        let child_dst_id = result.node_id;
373                        self.copy_subtree(child_src_id, dst, child_dst_id);
374                    }
375                }
376            }
377            NodeValue::Tuple(tuple) => {
378                for (idx, &child_src_id) in tuple.iter().enumerate() {
379                    if let Ok(result) = dst.add_tuple_element(idx as u8, dst_id) {
380                        let child_dst_id = result.node_id;
381                        self.copy_subtree(child_src_id, dst, child_dst_id);
382                    }
383                }
384            }
385            NodeValue::Map(map) => {
386                for (key, &child_src_id) in map.iter() {
387                    if let Ok(result) = dst.add_map_child(key.clone(), dst_id) {
388                        let child_dst_id = result.node_id;
389                        self.copy_subtree(child_src_id, dst, child_dst_id);
390                    }
391                }
392            }
393            _ => {}
394        }
395    }
396}
397
398/// Commands
399impl EureDocument {
400    pub fn replace_with_primitive(&mut self, value: PrimitiveValue) -> Result<(), InsertErrorKind> {
401        self.nodes.clear();
402        self.nodes[self.root.0].content = NodeValue::Primitive(value);
403        Ok(())
404    }
405
406    pub fn reset_as_map(&mut self) -> Result<(), InsertErrorKind> {
407        self.nodes.clear();
408        self.nodes[self.root.0].content = NodeValue::Map(Default::default());
409        Ok(())
410    }
411}
412
413#[cfg(test)]
414mod tests {
415    use super::*;
416
417    fn identifier(s: &str) -> Identifier {
418        s.parse().unwrap()
419    }
420
421    #[test]
422    fn test_add_map_child_success() {
423        let mut doc = EureDocument::new();
424        let map_id = {
425            let doc: &mut EureDocument = &mut doc;
426            doc.create_node(NodeValue::empty_map())
427        };
428        let key = ObjectKey::String("test_key".to_string());
429
430        let child_id = doc
431            .add_map_child(key.clone(), map_id)
432            .expect("Failed to add map child")
433            .node_id;
434
435        let map = doc.node(map_id).as_map().expect("Expected map");
436        assert_eq!(map.get(&key), Some(&child_id));
437    }
438
439    #[test]
440    fn test_add_map_child_error_expected_map() {
441        let mut doc = EureDocument::new();
442        let primitive_id = {
443            let doc: &mut EureDocument = &mut doc;
444            doc.create_node(NodeValue::Primitive(PrimitiveValue::Null))
445        };
446        let key = ObjectKey::String("test".to_string());
447
448        let result = doc.add_map_child(key, primitive_id);
449        assert_eq!(result.err(), Some(InsertErrorKind::ExpectedMap));
450    }
451
452    #[test]
453    fn test_add_map_child_error_already_assigned() {
454        let mut doc = EureDocument::new();
455        let root_id = doc.get_root_id();
456        let key = ObjectKey::String("test".to_string());
457
458        let _result1 = doc
459            .add_map_child(key.clone(), root_id)
460            .expect("First add should succeed");
461
462        let result2 = doc.add_map_child(key.clone(), root_id);
463        assert_eq!(
464            result2.err(),
465            Some(InsertErrorKind::AlreadyAssigned { key })
466        );
467    }
468
469    #[test]
470    fn test_add_extension_success_multiple() {
471        let mut doc = EureDocument::new();
472        let root_id = doc.get_root_id();
473        let id1 = identifier("ext1");
474        let id2 = identifier("ext2");
475
476        let node_id1 = doc
477            .add_extension(id1.clone(), root_id)
478            .expect("Failed to add extension")
479            .node_id;
480
481        let node_id2 = doc
482            .add_extension(id2.clone(), root_id)
483            .expect("Failed to add extension")
484            .node_id;
485
486        let node = doc.node(root_id);
487        assert_eq!(node.extensions.get(&id1), Some(&node_id1));
488        assert_eq!(node.extensions.get(&id2), Some(&node_id2));
489    }
490
491    #[test]
492    fn test_add_extension_success() {
493        let mut doc = EureDocument::new();
494        let primitive_id = {
495            let doc: &mut EureDocument = &mut doc;
496            doc.create_node(NodeValue::Primitive(PrimitiveValue::Null))
497        };
498        let identifier = identifier("ext");
499
500        let node_id = doc
501            .add_extension(identifier.clone(), primitive_id)
502            .expect("Failed to add extension")
503            .node_id;
504
505        let node = doc.node(primitive_id);
506        assert_eq!(node.extensions.get(&identifier), Some(&node_id));
507    }
508
509    #[test]
510    fn test_add_extension_error_already_assigned() {
511        let mut doc = EureDocument::new();
512        let map_id = {
513            let doc: &mut EureDocument = &mut doc;
514            doc.create_node(NodeValue::empty_map())
515        };
516        let identifier = identifier("ext");
517
518        let _result1 = doc
519            .add_extension(identifier.clone(), map_id)
520            .expect("First add should succeed");
521
522        let result2 = doc.add_extension(identifier.clone(), map_id);
523        assert_eq!(
524            result2.err(),
525            Some(InsertErrorKind::AlreadyAssignedExtension { identifier })
526        );
527    }
528
529    #[test]
530    fn test_add_tuple_element_success_index_0() {
531        let mut doc = EureDocument::new();
532        let tuple_id = {
533            let doc: &mut EureDocument = &mut doc;
534            doc.create_node(NodeValue::empty_tuple())
535        };
536
537        let node_id = doc
538            .add_tuple_element(0, tuple_id)
539            .expect("Failed to add tuple element")
540            .node_id;
541
542        let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
543        assert_eq!(tuple.to_vec(), vec![node_id]);
544    }
545
546    #[test]
547    fn test_add_tuple_element_success_sequential() {
548        let mut doc = EureDocument::new();
549        let tuple_id = {
550            let doc: &mut EureDocument = &mut doc;
551            doc.create_node(NodeValue::empty_tuple())
552        };
553
554        let node_id1 = doc
555            .add_tuple_element(0, tuple_id)
556            .expect("Failed to add tuple element")
557            .node_id;
558
559        let node_id2 = doc
560            .add_tuple_element(1, tuple_id)
561            .expect("Failed to add tuple element")
562            .node_id;
563
564        let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
565        assert_eq!(tuple.to_vec(), vec![node_id1, node_id2]);
566    }
567
568    #[test]
569    fn test_add_tuple_element_error_expected_tuple() {
570        let mut doc = EureDocument::new();
571        let map_id = {
572            let doc: &mut EureDocument = &mut doc;
573            doc.create_node(NodeValue::empty_map())
574        };
575
576        let result = doc.add_tuple_element(0, map_id);
577        assert_eq!(result.err(), Some(InsertErrorKind::ExpectedTuple));
578    }
579
580    #[test]
581    fn test_add_tuple_element_error_invalid_index() {
582        let mut doc = EureDocument::new();
583        let tuple_id = {
584            let doc: &mut EureDocument = &mut doc;
585            doc.create_node(NodeValue::empty_tuple())
586        };
587
588        let result = doc.add_tuple_element(1, tuple_id);
589        assert_eq!(
590            result.err(),
591            Some(InsertErrorKind::TupleIndexInvalid {
592                index: 1,
593                expected_index: 0
594            })
595        );
596    }
597
598    #[test]
599    fn test_add_array_element_success_push() {
600        let mut doc = EureDocument::new();
601        let array_id = {
602            let doc: &mut EureDocument = &mut doc;
603            doc.create_node(NodeValue::empty_array())
604        };
605
606        let node_id = doc
607            .add_array_element(None, array_id)
608            .expect("Failed to add array element")
609            .node_id;
610
611        let array = doc.node(array_id).as_array().expect("Expected array");
612        assert_eq!(array.to_vec(), vec![node_id]);
613    }
614
615    #[test]
616    fn test_add_array_element_success_at_index() {
617        let mut doc = EureDocument::new();
618        let array_id = {
619            let doc: &mut EureDocument = &mut doc;
620            doc.create_node(NodeValue::empty_array())
621        };
622
623        let node_id1 = doc
624            .add_array_element(Some(0), array_id)
625            .expect("Failed to add array element")
626            .node_id;
627
628        let node_id2 = doc
629            .add_array_element(Some(1), array_id)
630            .expect("Failed to add array element")
631            .node_id;
632
633        let array = doc.node(array_id).as_array().expect("Expected array");
634        assert_eq!(array.to_vec(), vec![node_id1, node_id2]);
635    }
636
637    #[test]
638    fn test_add_array_element_error_expected_array() {
639        let mut doc = EureDocument::new();
640        let map_id = {
641            let doc: &mut EureDocument = &mut doc;
642            doc.create_node(NodeValue::empty_map())
643        };
644
645        let result = doc.add_array_element(None, map_id);
646        assert_eq!(result.err(), Some(InsertErrorKind::ExpectedArray));
647    }
648
649    #[test]
650    fn test_add_array_element_error_invalid_index() {
651        let mut doc = EureDocument::new();
652        let array_id = {
653            let doc: &mut EureDocument = &mut doc;
654            doc.create_node(NodeValue::empty_array())
655        };
656
657        let result = doc.add_array_element(Some(1), array_id);
658        assert_eq!(
659            result.err(),
660            Some(InsertErrorKind::ArrayIndexInvalid {
661                index: 1,
662                expected_index: 0
663            })
664        );
665    }
666
667    #[test]
668    fn test_add_child_by_segment_ident() {
669        let mut doc = EureDocument::new();
670        let root_id = doc.get_root_id();
671        let identifier = identifier("test");
672        let segment = PathSegment::Ident(identifier.clone());
673
674        let result = doc.add_child_by_segment(segment, root_id);
675        assert!(result.is_ok());
676
677        let map = doc.node(root_id).as_map().expect("Expected map");
678        let key = ObjectKey::String(identifier.into_string());
679        assert!(map.get(&key).is_some());
680    }
681
682    #[test]
683    fn test_add_child_by_segment_value() {
684        let mut doc = EureDocument::new();
685        let root_id = doc.get_root_id();
686        let key = ObjectKey::String("test".to_string());
687        let segment = PathSegment::Value(key.clone());
688
689        let result = doc.add_child_by_segment(segment, root_id);
690        assert!(result.is_ok());
691
692        let map = doc.node(root_id).as_map().expect("Expected map");
693        assert!(map.get(&key).is_some());
694    }
695
696    #[test]
697    fn test_add_child_by_segment_extension() {
698        let mut doc = EureDocument::new();
699        let root_id = doc.get_root_id();
700        let identifier = identifier("ext");
701        let segment = PathSegment::Extension(identifier.clone());
702
703        let result = doc.add_child_by_segment(segment, root_id);
704        assert!(result.is_ok());
705
706        let node = doc.node(root_id);
707        assert!(node.extensions.contains_key(&identifier));
708    }
709
710    #[test]
711    fn test_add_child_by_segment_tuple_index() {
712        let mut doc = EureDocument::new();
713        let tuple_id = {
714            let doc: &mut EureDocument = &mut doc;
715            doc.create_node(NodeValue::empty_tuple())
716        };
717        let segment = PathSegment::TupleIndex(0);
718
719        let result = doc.add_child_by_segment(segment, tuple_id);
720        assert!(result.is_ok());
721
722        let tuple = doc.node(tuple_id).as_tuple().expect("Expected tuple");
723        assert_eq!(tuple.len(), 1);
724    }
725
726    #[test]
727    fn test_add_child_by_segment_array_index_none() {
728        let mut doc = EureDocument::new();
729        let array_id = {
730            let doc: &mut EureDocument = &mut doc;
731            doc.create_node(NodeValue::empty_array())
732        };
733        let segment = PathSegment::ArrayIndex(None);
734
735        let result = doc.add_child_by_segment(segment, array_id);
736        assert!(result.is_ok());
737
738        let array = doc.node(array_id).as_array().expect("Expected array");
739        assert_eq!(array.len(), 1);
740    }
741
742    #[test]
743    fn test_add_child_by_segment_array_index_some() {
744        let mut doc = EureDocument::new();
745        let array_id = {
746            let doc: &mut EureDocument = &mut doc;
747            doc.create_node(NodeValue::empty_array())
748        };
749        let segment = PathSegment::ArrayIndex(Some(0));
750
751        let result = doc.add_child_by_segment(segment, array_id);
752        assert!(result.is_ok());
753
754        let array = doc.node(array_id).as_array().expect("Expected array");
755        assert_eq!(array.len(), 1);
756    }
757
758    #[test]
759    fn test_resolve_ident_idempotent() {
760        let mut doc = EureDocument::new();
761        let root_id = doc.get_root_id();
762        let identifier = identifier("field");
763
764        // First call - creates new node
765        let node_id1 = doc
766            .resolve_child_by_segment(PathSegment::Ident(identifier.clone()), root_id)
767            .expect("First call failed")
768            .node_id;
769
770        // Second call - returns existing node
771        let node_id2 = doc
772            .resolve_child_by_segment(PathSegment::Ident(identifier), root_id)
773            .expect("Second call failed")
774            .node_id;
775
776        assert_eq!(node_id1, node_id2);
777    }
778
779    #[test]
780    fn test_resolve_value_idempotent() {
781        let mut doc = EureDocument::new();
782        let root_id = doc.get_root_id();
783        let object_key = ObjectKey::String("key".to_string());
784
785        // First call - creates new node
786        let node_id1 = doc
787            .resolve_child_by_segment(PathSegment::Value(object_key.clone()), root_id)
788            .expect("First call failed")
789            .node_id;
790
791        // Second call - returns existing node
792        let node_id2 = doc
793            .resolve_child_by_segment(PathSegment::Value(object_key), root_id)
794            .expect("Second call failed")
795            .node_id;
796
797        assert_eq!(node_id1, node_id2);
798    }
799
800    #[test]
801    fn test_resolve_extension_idempotent() {
802        let mut doc = EureDocument::new();
803        let root_id = doc.get_root_id();
804        let identifier = identifier("ext");
805
806        // First call - creates new node
807        let node_id1 = doc
808            .resolve_child_by_segment(PathSegment::Extension(identifier.clone()), root_id)
809            .expect("First call failed")
810            .node_id;
811
812        // Second call - returns existing node
813        let node_id2 = doc
814            .resolve_child_by_segment(PathSegment::Extension(identifier), root_id)
815            .expect("Second call failed")
816            .node_id;
817
818        assert_eq!(node_id1, node_id2);
819    }
820
821    #[test]
822    fn test_resolve_tuple_index_idempotent() {
823        let mut doc = EureDocument::new();
824        let parent_id = doc.create_node_uninitialized();
825
826        // First call - creates new node
827        let node_id1 = doc
828            .resolve_child_by_segment(PathSegment::TupleIndex(0), parent_id)
829            .expect("First call failed")
830            .node_id;
831
832        // Second call - returns existing node
833        let node_id2 = doc
834            .resolve_child_by_segment(PathSegment::TupleIndex(0), parent_id)
835            .expect("Second call failed")
836            .node_id;
837
838        assert_eq!(node_id1, node_id2);
839    }
840
841    #[test]
842    fn test_resolve_array_index_some_idempotent() {
843        let mut doc = EureDocument::new();
844        let parent_id = doc.create_node_uninitialized();
845
846        // First call - creates new node
847        let node_id1 = doc
848            .resolve_child_by_segment(PathSegment::ArrayIndex(Some(0)), parent_id)
849            .expect("First call failed")
850            .node_id;
851
852        // Second call - returns existing node
853        let node_id2 = doc
854            .resolve_child_by_segment(PathSegment::ArrayIndex(Some(0)), parent_id)
855            .expect("Second call failed")
856            .node_id;
857
858        assert_eq!(node_id1, node_id2);
859    }
860
861    #[test]
862    fn test_resolve_array_index_none_always_creates_new() {
863        let mut doc = EureDocument::new();
864        let parent_id = doc.create_node_uninitialized();
865
866        // First call - creates new node
867        let node_id1 = doc
868            .resolve_child_by_segment(PathSegment::ArrayIndex(None), parent_id)
869            .expect("First call failed")
870            .node_id;
871
872        // Second call - creates another new node (NOT idempotent)
873        let node_id2 = doc
874            .resolve_child_by_segment(PathSegment::ArrayIndex(None), parent_id)
875            .expect("Second call failed")
876            .node_id;
877
878        // ArrayIndex(None) always creates new nodes (push operation)
879        assert_ne!(node_id1, node_id2);
880
881        // Verify both nodes exist in array
882        let array = doc.node(parent_id).as_array().expect("Expected array");
883        assert_eq!(array.len(), 2);
884        assert_eq!(array.get(0).unwrap(), node_id1);
885        assert_eq!(array.get(1).unwrap(), node_id2);
886    }
887
888    #[test]
889    fn test_get_node_with_valid_id() {
890        let mut doc = EureDocument::new();
891        let node_id = doc.create_node(NodeValue::Primitive(PrimitiveValue::Null));
892
893        let result = doc.get_node(node_id);
894        assert!(result.is_some());
895
896        let node = result.unwrap();
897        assert_eq!(node.content, NodeValue::Primitive(PrimitiveValue::Null));
898    }
899
900    #[test]
901    fn test_get_node_with_invalid_id() {
902        let doc = EureDocument::new();
903        // Create an invalid NodeId that's out of bounds
904        let invalid_id = NodeId(9999);
905
906        let result = doc.get_node(invalid_id);
907        assert!(result.is_none());
908    }
909
910    #[test]
911    fn test_get_node_mut_with_valid_id() {
912        let mut doc = EureDocument::new();
913        let node_id = doc.create_node(NodeValue::Primitive(PrimitiveValue::Null));
914
915        let result = doc.get_node_mut(node_id);
916        assert!(result.is_some());
917
918        // Verify we can mutate through the returned reference
919        let node = result.unwrap();
920        node.content = NodeValue::Primitive(PrimitiveValue::Bool(true));
921
922        // Verify the mutation persisted
923        assert_eq!(
924            doc.node(node_id).content,
925            NodeValue::Primitive(PrimitiveValue::Bool(true))
926        );
927    }
928
929    #[test]
930    fn test_get_node_mut_with_invalid_id() {
931        let mut doc = EureDocument::new();
932        // Create an invalid NodeId that's out of bounds
933        let invalid_id = NodeId(9999);
934
935        let result = doc.get_node_mut(invalid_id);
936        assert!(result.is_none());
937    }
938
939    #[test]
940    fn test_partialeq_empty_documents() {
941        let doc1 = EureDocument::new();
942        let doc2 = EureDocument::new();
943        assert_eq!(doc1, doc2);
944    }
945
946    #[test]
947    fn test_partialeq_primitive_documents() {
948        let doc1 = EureDocument::new_primitive(PrimitiveValue::Bool(true));
949        let doc2 = EureDocument::new_primitive(PrimitiveValue::Bool(true));
950        let doc3 = EureDocument::new_primitive(PrimitiveValue::Bool(false));
951
952        assert_eq!(doc1, doc2);
953        assert_ne!(doc1, doc3);
954    }
955
956    #[test]
957    fn test_partialeq_with_map_children() {
958        let mut doc1 = EureDocument::new();
959        let mut doc2 = EureDocument::new();
960
961        let root1 = doc1.get_root_id();
962        let root2 = doc2.get_root_id();
963
964        let key = ObjectKey::String("test".to_string());
965
966        doc1.add_map_child(key.clone(), root1)
967            .expect("Failed to add child");
968        doc2.add_map_child(key.clone(), root2)
969            .expect("Failed to add child");
970
971        assert_eq!(doc1, doc2);
972    }
973
974    #[test]
975    fn test_partialeq_with_different_map_children() {
976        let mut doc1 = EureDocument::new();
977        let mut doc2 = EureDocument::new();
978
979        let root1 = doc1.get_root_id();
980        let root2 = doc2.get_root_id();
981
982        doc1.add_map_child(ObjectKey::String("key1".to_string()), root1)
983            .expect("Failed to add child");
984        doc2.add_map_child(ObjectKey::String("key2".to_string()), root2)
985            .expect("Failed to add child");
986
987        assert_ne!(doc1, doc2);
988    }
989
990    #[test]
991    fn test_partialeq_with_extensions() {
992        let mut doc1 = EureDocument::new();
993        let mut doc2 = EureDocument::new();
994
995        let root1 = doc1.get_root_id();
996        let root2 = doc2.get_root_id();
997
998        let ext_id = identifier("ext");
999
1000        doc1.add_extension(ext_id.clone(), root1)
1001            .expect("Failed to add extension");
1002        doc2.add_extension(ext_id.clone(), root2)
1003            .expect("Failed to add extension");
1004
1005        assert_eq!(doc1, doc2);
1006    }
1007
1008    #[test]
1009    fn test_partialeq_with_different_extensions() {
1010        let mut doc1 = EureDocument::new();
1011        let mut doc2 = EureDocument::new();
1012
1013        let root1 = doc1.get_root_id();
1014        let root2 = doc2.get_root_id();
1015
1016        doc1.add_extension(identifier("ext1"), root1)
1017            .expect("Failed to add extension");
1018        doc2.add_extension(identifier("ext2"), root2)
1019            .expect("Failed to add extension");
1020
1021        assert_ne!(doc1, doc2);
1022    }
1023
1024    #[test]
1025    fn test_partialeq_with_arrays() {
1026        let mut doc1 = EureDocument::new();
1027        let mut doc2 = EureDocument::new();
1028
1029        // Create array in doc1
1030        let array_id1 = doc1.create_node(NodeValue::empty_array());
1031        doc1.add_array_element(None, array_id1)
1032            .expect("Failed to add array element");
1033        doc1.root = array_id1;
1034
1035        // Create array in doc2
1036        let array_id2 = doc2.create_node(NodeValue::empty_array());
1037        doc2.add_array_element(None, array_id2)
1038            .expect("Failed to add array element");
1039        doc2.root = array_id2;
1040
1041        assert_eq!(doc1, doc2);
1042    }
1043
1044    #[test]
1045    fn test_partialeq_with_tuples() {
1046        let mut doc1 = EureDocument::new();
1047        let mut doc2 = EureDocument::new();
1048
1049        // Create tuple in doc1
1050        let tuple_id1 = doc1.create_node(NodeValue::empty_tuple());
1051        doc1.add_tuple_element(0, tuple_id1)
1052            .expect("Failed to add tuple element");
1053        doc1.root = tuple_id1;
1054
1055        // Create tuple in doc2
1056        let tuple_id2 = doc2.create_node(NodeValue::empty_tuple());
1057        doc2.add_tuple_element(0, tuple_id2)
1058            .expect("Failed to add tuple element");
1059        doc2.root = tuple_id2;
1060
1061        assert_eq!(doc1, doc2);
1062    }
1063
1064    #[test]
1065    fn test_partialeq_nested_structure() {
1066        let mut doc1 = EureDocument::new();
1067        let mut doc2 = EureDocument::new();
1068
1069        // Create nested structure in doc1
1070        let root1 = doc1.get_root_id();
1071        let child1 = doc1
1072            .add_map_child(ObjectKey::String("child".to_string()), root1)
1073            .expect("Failed to add child")
1074            .node_id;
1075        doc1.node_mut(child1).content = NodeValue::Primitive(PrimitiveValue::Bool(true));
1076
1077        // Create nested structure in doc2
1078        let root2 = doc2.get_root_id();
1079        let child2 = doc2
1080            .add_map_child(ObjectKey::String("child".to_string()), root2)
1081            .expect("Failed to add child")
1082            .node_id;
1083        doc2.node_mut(child2).content = NodeValue::Primitive(PrimitiveValue::Bool(true));
1084
1085        assert_eq!(doc1, doc2);
1086    }
1087
1088    #[test]
1089    fn test_partialeq_ignores_node_id_values() {
1090        let mut doc1 = EureDocument::new();
1091        let mut doc2 = EureDocument::new();
1092
1093        // Create a more complex structure in doc1
1094        let root1 = doc1.get_root_id();
1095        let _intermediate = doc1.create_node(NodeValue::Primitive(PrimitiveValue::Null));
1096        let child1 = doc1
1097            .add_map_child(ObjectKey::String("key".to_string()), root1)
1098            .expect("Failed")
1099            .node_id;
1100
1101        // Create the same structure in doc2 (without intermediate node)
1102        let root2 = doc2.get_root_id();
1103        let child2 = doc2
1104            .add_map_child(ObjectKey::String("key".to_string()), root2)
1105            .expect("Failed")
1106            .node_id;
1107
1108        // Even though child1 and child2 have different NodeId values,
1109        // the structures should be equal
1110        assert_eq!(doc1, doc2);
1111
1112        // Verify that NodeIds are actually different
1113        assert_ne!(child1.0, child2.0);
1114    }
1115}