1use crate::{
2 map::PartialNodeMap,
3 prelude_internal::*,
4 value::{PartialObjectKey, ValueKind},
5};
6
7#[derive(Debug, Clone)]
8pub struct Node {
12 pub content: NodeValue,
13 pub extensions: Map<Identifier, NodeId>,
14}
15
16pub struct NodeMut<'d> {
17 document: &'d mut EureDocument,
18 pub node_id: NodeId,
19}
20
21impl<'d> core::fmt::Debug for NodeMut<'d> {
22 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23 match self.document.get_node(self.node_id) {
24 Some(node) => f
25 .debug_tuple("NodeMut")
26 .field(&self.node_id)
27 .field(node)
28 .finish(),
29 None => f
30 .debug_tuple("NodeMut")
31 .field(&self.node_id)
32 .field(&"<invalid>")
33 .finish(),
34 }
35 }
36}
37
38impl<'d> NodeMut<'d> {
39 pub fn new(document: &'d mut EureDocument, node_id: NodeId) -> Self {
40 Self { document, node_id }
41 }
42
43 pub fn add_map_child(self, object_key: ObjectKey) -> Result<NodeMut<'d>, InsertErrorKind> {
44 self.document.add_map_child(object_key, self.node_id)
45 }
46
47 pub fn add_extension(self, identifier: Identifier) -> Result<NodeMut<'d>, InsertErrorKind> {
48 self.document.add_extension(identifier, self.node_id)
49 }
50
51 pub fn add_tuple_element(self, index: u8) -> Result<NodeMut<'d>, InsertErrorKind> {
52 self.document.add_tuple_element(index, self.node_id)
53 }
54
55 pub fn add_array_element(self, index: Option<usize>) -> Result<NodeMut<'d>, InsertErrorKind> {
56 self.document.add_array_element(index, self.node_id)
57 }
58
59 pub fn add_child_by_segment(
60 self,
61 segment: PathSegment,
62 ) -> Result<NodeMut<'d>, InsertErrorKind> {
63 self.document.add_child_by_segment(segment, self.node_id)
64 }
65
66 pub fn get_extension(self, ident: &Identifier) -> Option<NodeMut<'d>> {
67 let node_id = self.document.node(self.node_id).extensions.get(ident)?;
68 Some(NodeMut::new(self.document, *node_id))
69 }
70
71 pub fn as_map(self) -> Option<&'d NodeMap> {
74 self.document.node(self.node_id).as_map()
75 }
76
77 pub fn as_array(self) -> Option<&'d NodeArray> {
78 self.document.node(self.node_id).as_array()
79 }
80
81 pub fn as_tuple(self) -> Option<&'d NodeTuple> {
82 self.document.node(self.node_id).as_tuple()
83 }
84
85 pub fn require_map(self) -> Result<&'d mut NodeMap, InsertErrorKind> {
86 self.document.node_mut(self.node_id).require_map()
87 }
88
89 pub fn as_partial_map(self) -> Option<&'d PartialNodeMap> {
90 self.document.node(self.node_id).as_partial_map()
91 }
92
93 pub fn require_partial_map(self) -> Result<&'d mut PartialNodeMap, InsertErrorKind> {
94 self.document.node_mut(self.node_id).require_partial_map()
95 }
96
97 pub fn require_tuple(self) -> Result<&'d mut NodeTuple, InsertErrorKind> {
98 self.document.node_mut(self.node_id).require_tuple()
99 }
100
101 pub fn require_array(self) -> Result<&'d mut NodeArray, InsertErrorKind> {
102 self.document.node_mut(self.node_id).require_array()
103 }
104}
105
106impl Node {
107 pub fn as_map(&self) -> Option<&NodeMap> {
108 match &self.content {
109 NodeValue::Map(map) => Some(map),
110 _ => None,
111 }
112 }
113
114 pub fn as_partial_map(&self) -> Option<&PartialNodeMap> {
115 match &self.content {
116 NodeValue::PartialMap(pm) => Some(pm),
117 _ => None,
118 }
119 }
120
121 pub fn as_array(&self) -> Option<&NodeArray> {
122 match &self.content {
123 NodeValue::Array(array) => Some(array),
124 _ => None,
125 }
126 }
127
128 pub fn as_tuple(&self) -> Option<&NodeTuple> {
129 match &self.content {
130 NodeValue::Tuple(tuple) => Some(tuple),
131 _ => None,
132 }
133 }
134
135 pub fn as_primitive(&self) -> Option<&PrimitiveValue> {
136 match &self.content {
137 NodeValue::Primitive(primitive) => Some(primitive),
138 _ => None,
139 }
140 }
141
142 pub fn get_extension(&self, ident: &Identifier) -> Option<NodeId> {
143 self.extensions.get(ident).copied()
144 }
145
146 pub(crate) fn require_map(&mut self) -> Result<&mut NodeMap, InsertErrorKind> {
147 if self.content.is_hole() {
148 self.content = NodeValue::Map(Default::default());
149 let NodeValue::Map(map) = &mut self.content else {
150 unreachable!();
151 };
152 Ok(map)
153 } else if let NodeValue::Map(map) = &mut self.content {
154 Ok(map)
155 } else {
156 Err(InsertErrorKind::ExpectedMap)
157 }
158 }
159
160 pub(crate) fn require_tuple(&mut self) -> Result<&mut NodeTuple, InsertErrorKind> {
161 if self.content.is_hole() {
162 self.content = NodeValue::Tuple(Default::default());
163 let NodeValue::Tuple(tuple) = &mut self.content else {
164 unreachable!();
165 };
166 Ok(tuple)
167 } else if let NodeValue::Tuple(tuple) = &mut self.content {
168 Ok(tuple)
169 } else {
170 Err(InsertErrorKind::ExpectedTuple)
171 }
172 }
173
174 pub(crate) fn require_array(&mut self) -> Result<&mut NodeArray, InsertErrorKind> {
175 if self.content.is_hole() {
176 self.content = NodeValue::Array(Default::default());
177 let NodeValue::Array(array) = &mut self.content else {
178 unreachable!();
179 };
180 Ok(array)
181 } else if let NodeValue::Array(array) = &mut self.content {
182 Ok(array)
183 } else {
184 Err(InsertErrorKind::ExpectedArray)
185 }
186 }
187
188 pub(crate) fn require_partial_map(&mut self) -> Result<&mut PartialNodeMap, InsertErrorKind> {
195 match &self.content {
196 NodeValue::Hole(_) => {
197 self.content = NodeValue::PartialMap(PartialNodeMap::new());
198 }
199 NodeValue::Map(map) => {
200 let entries: Vec<(ObjectKey, NodeId)> =
202 map.iter().map(|(k, &v)| (k.clone(), v)).collect();
203 self.content = NodeValue::PartialMap(PartialNodeMap::new());
204 let NodeValue::PartialMap(pm) = &mut self.content else {
205 unreachable!()
206 };
207 for (key, node_id) in entries {
208 pm.push(PartialObjectKey::from(key), node_id);
209 }
210 }
211 NodeValue::PartialMap(_) => {}
212 _ => return Err(InsertErrorKind::ExpectedMap),
213 }
214 let NodeValue::PartialMap(pm) = &mut self.content else {
215 unreachable!()
216 };
217 Ok(pm)
218 }
219}
220
221#[derive(Debug, PartialEq, Clone)]
222pub enum NodeValue {
223 Hole(Option<Identifier>),
226 Primitive(PrimitiveValue),
227 Array(NodeArray),
228 Map(NodeMap),
229 Tuple(NodeTuple),
230 PartialMap(PartialNodeMap),
236}
237
238impl NodeValue {
239 pub fn hole() -> Self {
241 Self::Hole(None)
242 }
243
244 pub fn labeled_hole(label: Identifier) -> Self {
246 Self::Hole(Some(label))
247 }
248
249 pub fn is_hole(&self) -> bool {
251 matches!(self, Self::Hole(_))
252 }
253
254 pub fn empty_map() -> Self {
255 Self::Map(NodeMap::new())
256 }
257
258 pub fn empty_array() -> Self {
259 Self::Array(NodeArray::new())
260 }
261
262 pub fn empty_tuple() -> Self {
263 Self::Tuple(NodeTuple::new())
264 }
265
266 pub fn empty_partial_map() -> Self {
267 Self::PartialMap(PartialNodeMap::new())
268 }
269
270 pub fn value_kind(&self) -> ValueKind {
271 match self {
272 Self::Hole(_) => ValueKind::Hole,
273 Self::Primitive(primitive) => primitive.kind(),
274 Self::Array(_) => ValueKind::Array,
275 Self::Map(_) => ValueKind::Map,
276 Self::Tuple(_) => ValueKind::Tuple,
277 Self::PartialMap(_) => ValueKind::PartialMap,
278 }
279 }
280}
281
282impl From<PrimitiveValue> for NodeValue {
287 fn from(p: PrimitiveValue) -> Self {
288 NodeValue::Primitive(p)
289 }
290}
291
292#[derive(Debug, Default, Clone, PartialEq, Eq, Plural)]
293#[plural(len, is_empty, iter, into_iter, new)]
294pub struct NodeArray(Vec<NodeId>);
295
296#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Plural)]
297#[plural(len, is_empty, iter, into_iter, new)]
298pub struct NodeTuple(Vec<NodeId>);
299
300pub type NodeMap = Map<ObjectKey, NodeId>;
301
302impl NodeTuple {
303 pub fn get(&self, index: usize) -> Option<NodeId> {
304 self.0.get(index).copied()
305 }
306
307 pub fn push(&mut self, node_id: NodeId) -> Result<(), InsertErrorKind> {
308 self.0.push(node_id);
309 Ok(())
310 }
311
312 pub fn add_at(&mut self, index: u8, node_id: NodeId) -> Result<(), InsertErrorKind> {
313 if index as usize != self.0.len() {
314 return Err(InsertErrorKind::TupleIndexInvalid {
315 index,
316 expected_index: self.0.len(),
317 });
318 }
319 self.0.insert(index as usize, node_id);
320 Ok(())
321 }
322
323 pub fn to_vec(&self) -> Vec<NodeId> {
324 self.0.clone()
325 }
326
327 pub fn from_vec(vec: Vec<NodeId>) -> Self {
328 Self(vec)
329 }
330}
331
332impl NodeArray {
333 pub fn get(&self, index: usize) -> Option<NodeId> {
334 self.0.get(index).copied()
335 }
336
337 pub fn push(&mut self, node_id: NodeId) -> Result<(), InsertErrorKind> {
338 self.0.push(node_id);
339 Ok(())
340 }
341
342 pub fn add_at(&mut self, index: usize, node_id: NodeId) -> Result<(), InsertErrorKind> {
343 if index != self.0.len() {
344 return Err(InsertErrorKind::ArrayIndexInvalid {
345 index,
346 expected_index: self.0.len(),
347 });
348 }
349 self.0.insert(index, node_id);
350 Ok(())
351 }
352
353 pub fn insert_at(&mut self, index: usize, node_id: NodeId) -> Result<(), InsertErrorKind> {
354 if index > self.0.len() {
355 return Err(InsertErrorKind::ArrayIndexInvalid {
356 index,
357 expected_index: self.0.len(),
358 });
359 }
360 self.0.insert(index, node_id);
361 Ok(())
362 }
363
364 pub fn remove_at(&mut self, index: usize) -> Option<NodeId> {
365 if index >= self.0.len() {
366 return None;
367 }
368 Some(self.0.remove(index))
369 }
370
371 pub fn to_vec(&self) -> Vec<NodeId> {
372 self.0.clone()
373 }
374
375 pub fn from_vec(vec: Vec<NodeId>) -> Self {
376 Self(vec)
377 }
378
379 pub fn try_into_array<const N: usize>(&self) -> Option<[NodeId; N]> {
382 self.0.as_slice().try_into().ok()
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::*;
389
390 fn identifier(s: &str) -> Identifier {
391 s.parse().unwrap()
392 }
393
394 #[test]
395 fn test_require_map_on_uninitialized() {
396 let mut node = Node {
397 content: NodeValue::hole(),
398 extensions: Map::new(),
399 };
400
401 let map = node.require_map().expect("Should convert to map");
402 assert_eq!(map.len(), 0);
403
404 assert!(node.as_map().is_some());
406 }
407
408 #[test]
409 fn test_require_map_on_existing_map() {
410 let mut node = Node {
411 content: NodeValue::Map(Default::default()),
412 extensions: Map::new(),
413 };
414
415 let map = node.require_map().expect("Should return existing map");
416 assert_eq!(map.len(), 0);
417 }
418
419 #[test]
420 fn test_require_map_on_wrong_type() {
421 let mut node = Node {
422 content: NodeValue::Primitive(PrimitiveValue::Null),
423 extensions: Map::new(),
424 };
425
426 let result = node.require_map();
427 assert_eq!(result, Err(InsertErrorKind::ExpectedMap));
428 }
429
430 #[test]
431 fn test_require_tuple_on_uninitialized() {
432 let mut node = Node {
433 content: NodeValue::hole(),
434 extensions: Map::new(),
435 };
436
437 let tuple = node.require_tuple().expect("Should convert to tuple");
438 assert_eq!(tuple.len(), 0);
439
440 assert!(node.as_tuple().is_some());
442 }
443
444 #[test]
445 fn test_require_tuple_on_existing_tuple() {
446 let mut node = Node {
447 content: NodeValue::Tuple(Default::default()),
448 extensions: Map::new(),
449 };
450
451 let tuple = node.require_tuple().expect("Should return existing tuple");
452 assert_eq!(tuple.len(), 0);
453 }
454
455 #[test]
456 fn test_require_tuple_on_wrong_type() {
457 let mut node = Node {
458 content: NodeValue::Primitive(PrimitiveValue::Null),
459 extensions: Map::new(),
460 };
461
462 let result = node.require_tuple();
463 assert_eq!(result, Err(InsertErrorKind::ExpectedTuple));
464 }
465
466 #[test]
467 fn test_require_array_on_uninitialized() {
468 let mut node = Node {
469 content: NodeValue::hole(),
470 extensions: Map::new(),
471 };
472
473 let array = node.require_array().expect("Should convert to array");
474 assert_eq!(array.len(), 0);
475
476 assert!(node.as_array().is_some());
478 }
479
480 #[test]
481 fn test_require_array_on_existing_array() {
482 let mut node = Node {
483 content: NodeValue::Array(Default::default()),
484 extensions: Map::new(),
485 };
486
487 let array = node.require_array().expect("Should return existing array");
488 assert_eq!(array.len(), 0);
489 }
490
491 #[test]
492 fn test_require_array_on_wrong_type() {
493 let mut node = Node {
494 content: NodeValue::Primitive(PrimitiveValue::Null),
495 extensions: Map::new(),
496 };
497
498 let result = node.require_array();
499 assert_eq!(result, Err(InsertErrorKind::ExpectedArray));
500 }
501
502 #[test]
503 fn test_node_get_extension_exists() {
504 let mut doc = EureDocument::new();
505 let root_id = doc.get_root_id();
506 let ext_identifier = identifier("test_ext");
507
508 let ext_node_id = doc
510 .add_extension(ext_identifier.clone(), root_id)
511 .expect("Failed to add extension")
512 .node_id;
513
514 let root_node = doc.node(root_id);
516 let result = root_node.get_extension(&ext_identifier);
517
518 assert!(result.is_some());
519 assert_eq!(result.unwrap(), ext_node_id);
520 }
521
522 #[test]
523 fn test_node_get_extension_missing() {
524 let doc = EureDocument::new();
525 let root_id = doc.get_root_id();
526 let ext_identifier = identifier("nonexistent");
527
528 let root_node = doc.node(root_id);
530 let result = root_node.get_extension(&ext_identifier);
531
532 assert!(result.is_none());
533 }
534
535 #[test]
536 fn test_node_mut_get_extension_exists() {
537 let mut doc = EureDocument::new();
538 let root_id = doc.get_root_id();
539 let ext_identifier = identifier("test_ext");
540
541 let ext_node_id = doc
543 .add_extension(ext_identifier.clone(), root_id)
544 .expect("Failed to add extension")
545 .node_id;
546
547 let node_mut = NodeMut::new(&mut doc, root_id);
549 let result = node_mut.get_extension(&ext_identifier);
550
551 assert!(result.is_some());
552 let ext_node_mut = result.unwrap();
553 assert_eq!(ext_node_mut.node_id, ext_node_id);
554 }
555
556 #[test]
557 fn test_node_mut_get_extension_missing() {
558 let mut doc = EureDocument::new();
559 let root_id = doc.get_root_id();
560 let ext_identifier = identifier("nonexistent");
561
562 let node_mut = NodeMut::new(&mut doc, root_id);
564 let result = node_mut.get_extension(&ext_identifier);
565
566 assert!(result.is_none());
567 }
568
569 #[test]
570 fn test_node_mut_debug_valid_node() {
571 let mut doc = EureDocument::new();
572 let root_id = doc.get_root_id();
573
574 let node_mut = NodeMut::new(&mut doc, root_id);
576 let debug_output = alloc::format!("{:?}", node_mut);
577
578 assert!(debug_output.contains("NodeMut"));
580 assert!(debug_output.contains("NodeId"));
581 assert!(debug_output.contains("Node"));
582 assert!(debug_output.contains("Hole"));
583 }
584
585 #[test]
586 fn test_node_mut_debug_invalid_node() {
587 let mut doc = EureDocument::new();
588 let invalid_id = NodeId(999999); let node_mut = NodeMut::new(&mut doc, invalid_id);
592 let debug_output = alloc::format!("{:?}", node_mut);
593
594 assert!(debug_output.contains("NodeMut"));
596 assert!(debug_output.contains("<invalid>"));
597 }
598
599 #[test]
604 fn test_node_value_hole_is_hole() {
605 let value = NodeValue::hole();
606 assert!(value.is_hole());
607 assert_eq!(value, NodeValue::Hole(None));
608 }
609
610 #[test]
611 fn test_empty_containers_are_empty() {
612 let map = NodeValue::empty_map();
613 let array = NodeValue::empty_array();
614 let tuple = NodeValue::empty_tuple();
615
616 if let NodeValue::Map(m) = map {
617 assert!(m.is_empty());
618 } else {
619 panic!("empty_map should create Map");
620 }
621
622 if let NodeValue::Array(a) = array {
623 assert!(a.is_empty());
624 } else {
625 panic!("empty_array should create Array");
626 }
627
628 if let NodeValue::Tuple(t) = tuple {
629 assert!(t.is_empty());
630 } else {
631 panic!("empty_tuple should create Tuple");
632 }
633 }
634
635 #[test]
636 fn test_value_kind_correct() {
637 use crate::value::ValueKind;
638
639 let hole = NodeValue::hole();
640 assert_eq!(hole.value_kind(), ValueKind::Hole);
641
642 let primitive = NodeValue::Primitive(PrimitiveValue::Null);
643 assert_eq!(primitive.value_kind(), ValueKind::Null);
644
645 let bool_val = NodeValue::Primitive(PrimitiveValue::Bool(true));
646 assert_eq!(bool_val.value_kind(), ValueKind::Bool);
647
648 let array = NodeValue::empty_array();
649 assert_eq!(array.value_kind(), ValueKind::Array);
650
651 let map = NodeValue::empty_map();
652 assert_eq!(map.value_kind(), ValueKind::Map);
653
654 let tuple = NodeValue::empty_tuple();
655 assert_eq!(tuple.value_kind(), ValueKind::Tuple);
656 }
657
658 #[test]
659 fn test_require_map_idempotent() {
660 let mut node = Node {
661 content: NodeValue::empty_map(),
662 extensions: Map::new(),
663 };
664
665 for _ in 0..5 {
666 let result = node.require_map();
667 assert!(result.is_ok());
668 }
669
670 assert!(node.as_map().is_some());
671 }
672
673 #[test]
674 fn test_require_array_idempotent() {
675 let mut node = Node {
676 content: NodeValue::empty_array(),
677 extensions: Map::new(),
678 };
679
680 for _ in 0..5 {
681 let result = node.require_array();
682 assert!(result.is_ok());
683 }
684
685 assert!(node.as_array().is_some());
686 }
687
688 #[test]
689 fn test_require_tuple_idempotent() {
690 let mut node = Node {
691 content: NodeValue::empty_tuple(),
692 extensions: Map::new(),
693 };
694
695 for _ in 0..5 {
696 let result = node.require_tuple();
697 assert!(result.is_ok());
698 }
699
700 assert!(node.as_tuple().is_some());
701 }
702
703 #[test]
704 fn test_require_methods_type_mismatch() {
705 let mut array_node = Node {
707 content: NodeValue::empty_array(),
708 extensions: Map::new(),
709 };
710 assert_eq!(
711 array_node.require_map().err(),
712 Some(InsertErrorKind::ExpectedMap)
713 );
714 assert_eq!(
715 array_node.require_tuple().err(),
716 Some(InsertErrorKind::ExpectedTuple)
717 );
718
719 let mut map_node = Node {
721 content: NodeValue::empty_map(),
722 extensions: Map::new(),
723 };
724 assert_eq!(
725 map_node.require_array().err(),
726 Some(InsertErrorKind::ExpectedArray)
727 );
728 assert_eq!(
729 map_node.require_tuple().err(),
730 Some(InsertErrorKind::ExpectedTuple)
731 );
732
733 let mut tuple_node = Node {
735 content: NodeValue::empty_tuple(),
736 extensions: Map::new(),
737 };
738 assert_eq!(
739 tuple_node.require_map().err(),
740 Some(InsertErrorKind::ExpectedMap)
741 );
742 assert_eq!(
743 tuple_node.require_array().err(),
744 Some(InsertErrorKind::ExpectedArray)
745 );
746 }
747}
748
749#[cfg(test)]
750mod proptests {
751 extern crate std;
752
753 use super::*;
754 use proptest::prelude::*;
755 use std::vec::Vec;
756
757 proptest! {
762 #[test]
765 fn array_add_at_zero_on_empty_succeeds(_dummy in Just(())) {
766 let mut array = NodeArray::new();
767 let result = array.add_at(0, NodeId(1));
768 prop_assert!(result.is_ok(), "add_at(0) on empty array should succeed");
769 prop_assert_eq!(array.len(), 1);
770 }
771
772 #[test]
774 fn array_add_at_wrong_index_fails(index in 1usize..100) {
775 let mut array = NodeArray::new();
776
777 let result = array.add_at(index, NodeId(1));
778 prop_assert!(result.is_err(), "add_at({}) on empty array should fail", index);
779
780 match result {
781 Err(InsertErrorKind::ArrayIndexInvalid { index: i, expected_index }) => {
782 prop_assert_eq!(i, index);
783 prop_assert_eq!(expected_index, 0);
784 }
785 other => prop_assert!(false, "Expected ArrayIndexInvalid, got {:?}", other),
786 }
787 }
788
789 #[test]
791 fn array_sequential_add_succeeds(count in 1usize..50) {
792 let mut array = NodeArray::new();
793
794 for i in 0..count {
795 let result = array.add_at(i, NodeId(i));
796 prop_assert!(result.is_ok(), "add_at({}) should succeed", i);
797 }
798
799 prop_assert_eq!(array.len(), count);
800 }
801
802 #[test]
804 fn array_skip_index_fails(
805 fill_count in 0usize..10,
806 skip_amount in 1usize..10,
807 ) {
808 let mut array = NodeArray::new();
809
810 for i in 0..fill_count {
812 array.add_at(i, NodeId(i)).expect("Sequential add failed");
813 }
814
815 let bad_index = fill_count + skip_amount;
817 let result = array.add_at(bad_index, NodeId(bad_index));
818
819 match result {
820 Err(InsertErrorKind::ArrayIndexInvalid { index, expected_index }) => {
821 prop_assert_eq!(index, bad_index);
822 prop_assert_eq!(expected_index, fill_count);
823 }
824 other => prop_assert!(false, "Expected ArrayIndexInvalid, got {:?}", other),
825 }
826 }
827
828 #[test]
830 fn array_push_always_succeeds(count in 1usize..50) {
831 let mut array = NodeArray::new();
832
833 for i in 0..count {
834 let result = array.push(NodeId(i));
835 prop_assert!(result.is_ok(), "push should always succeed");
836 prop_assert_eq!(array.len(), i + 1);
837 }
838 }
839
840 #[test]
842 fn array_get_returns_correct_values(count in 1usize..20) {
843 let mut array = NodeArray::new();
844 let mut expected = Vec::new();
845
846 for i in 0..count {
847 let node_id = NodeId(i * 10); array.push(node_id).unwrap();
849 expected.push(node_id);
850 }
851
852 for (i, &expected_id) in expected.iter().enumerate() {
853 prop_assert_eq!(array.get(i), Some(expected_id),
854 "get({}) should return {:?}", i, expected_id);
855 }
856
857 prop_assert_eq!(array.get(count), None);
859 prop_assert_eq!(array.get(count + 100), None);
860 }
861
862 #[test]
864 fn array_to_vec_preserves_order(count in 0usize..20) {
865 let mut array = NodeArray::new();
866 let mut expected = Vec::new();
867
868 for i in 0..count {
869 let node_id = NodeId(i);
870 array.push(node_id).unwrap();
871 expected.push(node_id);
872 }
873
874 prop_assert_eq!(array.to_vec(), expected);
875 }
876
877 #[test]
879 fn array_from_vec_roundtrip(ids in proptest::collection::vec(0usize..1000, 0..20)) {
880 let node_ids: Vec<NodeId> = ids.iter().map(|&i| NodeId(i)).collect();
881 let array = NodeArray::from_vec(node_ids.clone());
882
883 prop_assert_eq!(array.len(), node_ids.len());
884 prop_assert_eq!(array.to_vec(), node_ids);
885 }
886 }
887
888 proptest! {
893 #[test]
896 fn tuple_add_at_zero_on_empty_succeeds(_dummy in Just(())) {
897 let mut tuple = NodeTuple::new();
898 let result = tuple.add_at(0, NodeId(1));
899 prop_assert!(result.is_ok(), "add_at(0) on empty tuple should succeed");
900 prop_assert_eq!(tuple.len(), 1);
901 }
902
903 #[test]
905 fn tuple_add_at_wrong_index_fails(index in 1u8..100) {
906 let mut tuple = NodeTuple::new();
907
908 let result = tuple.add_at(index, NodeId(1));
909 prop_assert!(result.is_err(), "add_at({}) on empty tuple should fail", index);
910
911 match result {
912 Err(InsertErrorKind::TupleIndexInvalid { index: i, expected_index }) => {
913 prop_assert_eq!(i, index);
914 prop_assert_eq!(expected_index, 0);
915 }
916 other => prop_assert!(false, "Expected TupleIndexInvalid, got {:?}", other),
917 }
918 }
919
920 #[test]
922 fn tuple_sequential_add_succeeds(count in 1u8..50) {
923 let mut tuple = NodeTuple::new();
924
925 for i in 0..count {
926 let result = tuple.add_at(i, NodeId(i as usize));
927 prop_assert!(result.is_ok(), "add_at({}) should succeed", i);
928 }
929
930 prop_assert_eq!(tuple.len(), count as usize);
931 }
932
933 #[test]
935 fn tuple_skip_index_fails(
936 fill_count in 0u8..10,
937 skip_amount in 1u8..10,
938 ) {
939 let mut tuple = NodeTuple::new();
940
941 for i in 0..fill_count {
943 tuple.add_at(i, NodeId(i as usize)).expect("Sequential add failed");
944 }
945
946 let bad_index = fill_count + skip_amount;
948 let result = tuple.add_at(bad_index, NodeId(bad_index as usize));
949
950 match result {
951 Err(InsertErrorKind::TupleIndexInvalid { index, expected_index }) => {
952 prop_assert_eq!(index, bad_index);
953 prop_assert_eq!(expected_index, fill_count as usize);
954 }
955 other => prop_assert!(false, "Expected TupleIndexInvalid, got {:?}", other),
956 }
957 }
958
959 #[test]
961 fn tuple_push_always_succeeds(count in 1usize..50) {
962 let mut tuple = NodeTuple::new();
963
964 for i in 0..count {
965 let result = tuple.push(NodeId(i));
966 prop_assert!(result.is_ok(), "push should always succeed");
967 prop_assert_eq!(tuple.len(), i + 1);
968 }
969 }
970
971 #[test]
973 fn tuple_get_returns_correct_values(count in 1usize..20) {
974 let mut tuple = NodeTuple::new();
975 let mut expected = Vec::new();
976
977 for i in 0..count {
978 let node_id = NodeId(i * 10);
979 tuple.push(node_id).unwrap();
980 expected.push(node_id);
981 }
982
983 for (i, &expected_id) in expected.iter().enumerate() {
984 prop_assert_eq!(tuple.get(i), Some(expected_id),
985 "get({}) should return {:?}", i, expected_id);
986 }
987
988 prop_assert_eq!(tuple.get(count), None);
990 prop_assert_eq!(tuple.get(count + 100), None);
991 }
992
993 #[test]
995 fn tuple_to_vec_preserves_order(count in 0usize..20) {
996 let mut tuple = NodeTuple::new();
997 let mut expected = Vec::new();
998
999 for i in 0..count {
1000 let node_id = NodeId(i);
1001 tuple.push(node_id).unwrap();
1002 expected.push(node_id);
1003 }
1004
1005 prop_assert_eq!(tuple.to_vec(), expected);
1006 }
1007
1008 #[test]
1010 fn tuple_from_vec_roundtrip(ids in proptest::collection::vec(0usize..1000, 0..20)) {
1011 let node_ids: Vec<NodeId> = ids.iter().map(|&i| NodeId(i)).collect();
1012 let tuple = NodeTuple::from_vec(node_ids.clone());
1013
1014 prop_assert_eq!(tuple.len(), node_ids.len());
1015 prop_assert_eq!(tuple.to_vec(), node_ids);
1016 }
1017 }
1018
1019 proptest! {
1024 #[test]
1026 fn node_value_labeled_hole_preserves_label(label in "[a-z][a-z0-9_-]{0,10}") {
1027 let identifier: Identifier = label.parse().unwrap();
1028 let value = NodeValue::labeled_hole(identifier.clone());
1029
1030 prop_assert!(value.is_hole());
1031 prop_assert_eq!(value, NodeValue::Hole(Some(identifier)));
1032 }
1033 }
1034}