eure_document/
document.rs

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