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 to_vec(&self) -> Vec<NodeId> {
354 self.0.clone()
355 }
356
357 pub fn from_vec(vec: Vec<NodeId>) -> Self {
358 Self(vec)
359 }
360
361 pub fn try_into_array<const N: usize>(&self) -> Option<[NodeId; N]> {
364 self.0.as_slice().try_into().ok()
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371
372 fn identifier(s: &str) -> Identifier {
373 s.parse().unwrap()
374 }
375
376 #[test]
377 fn test_require_map_on_uninitialized() {
378 let mut node = Node {
379 content: NodeValue::hole(),
380 extensions: Map::new(),
381 };
382
383 let map = node.require_map().expect("Should convert to map");
384 assert_eq!(map.len(), 0);
385
386 assert!(node.as_map().is_some());
388 }
389
390 #[test]
391 fn test_require_map_on_existing_map() {
392 let mut node = Node {
393 content: NodeValue::Map(Default::default()),
394 extensions: Map::new(),
395 };
396
397 let map = node.require_map().expect("Should return existing map");
398 assert_eq!(map.len(), 0);
399 }
400
401 #[test]
402 fn test_require_map_on_wrong_type() {
403 let mut node = Node {
404 content: NodeValue::Primitive(PrimitiveValue::Null),
405 extensions: Map::new(),
406 };
407
408 let result = node.require_map();
409 assert_eq!(result, Err(InsertErrorKind::ExpectedMap));
410 }
411
412 #[test]
413 fn test_require_tuple_on_uninitialized() {
414 let mut node = Node {
415 content: NodeValue::hole(),
416 extensions: Map::new(),
417 };
418
419 let tuple = node.require_tuple().expect("Should convert to tuple");
420 assert_eq!(tuple.len(), 0);
421
422 assert!(node.as_tuple().is_some());
424 }
425
426 #[test]
427 fn test_require_tuple_on_existing_tuple() {
428 let mut node = Node {
429 content: NodeValue::Tuple(Default::default()),
430 extensions: Map::new(),
431 };
432
433 let tuple = node.require_tuple().expect("Should return existing tuple");
434 assert_eq!(tuple.len(), 0);
435 }
436
437 #[test]
438 fn test_require_tuple_on_wrong_type() {
439 let mut node = Node {
440 content: NodeValue::Primitive(PrimitiveValue::Null),
441 extensions: Map::new(),
442 };
443
444 let result = node.require_tuple();
445 assert_eq!(result, Err(InsertErrorKind::ExpectedTuple));
446 }
447
448 #[test]
449 fn test_require_array_on_uninitialized() {
450 let mut node = Node {
451 content: NodeValue::hole(),
452 extensions: Map::new(),
453 };
454
455 let array = node.require_array().expect("Should convert to array");
456 assert_eq!(array.len(), 0);
457
458 assert!(node.as_array().is_some());
460 }
461
462 #[test]
463 fn test_require_array_on_existing_array() {
464 let mut node = Node {
465 content: NodeValue::Array(Default::default()),
466 extensions: Map::new(),
467 };
468
469 let array = node.require_array().expect("Should return existing array");
470 assert_eq!(array.len(), 0);
471 }
472
473 #[test]
474 fn test_require_array_on_wrong_type() {
475 let mut node = Node {
476 content: NodeValue::Primitive(PrimitiveValue::Null),
477 extensions: Map::new(),
478 };
479
480 let result = node.require_array();
481 assert_eq!(result, Err(InsertErrorKind::ExpectedArray));
482 }
483
484 #[test]
485 fn test_node_get_extension_exists() {
486 let mut doc = EureDocument::new();
487 let root_id = doc.get_root_id();
488 let ext_identifier = identifier("test_ext");
489
490 let ext_node_id = doc
492 .add_extension(ext_identifier.clone(), root_id)
493 .expect("Failed to add extension")
494 .node_id;
495
496 let root_node = doc.node(root_id);
498 let result = root_node.get_extension(&ext_identifier);
499
500 assert!(result.is_some());
501 assert_eq!(result.unwrap(), ext_node_id);
502 }
503
504 #[test]
505 fn test_node_get_extension_missing() {
506 let doc = EureDocument::new();
507 let root_id = doc.get_root_id();
508 let ext_identifier = identifier("nonexistent");
509
510 let root_node = doc.node(root_id);
512 let result = root_node.get_extension(&ext_identifier);
513
514 assert!(result.is_none());
515 }
516
517 #[test]
518 fn test_node_mut_get_extension_exists() {
519 let mut doc = EureDocument::new();
520 let root_id = doc.get_root_id();
521 let ext_identifier = identifier("test_ext");
522
523 let ext_node_id = doc
525 .add_extension(ext_identifier.clone(), root_id)
526 .expect("Failed to add extension")
527 .node_id;
528
529 let node_mut = NodeMut::new(&mut doc, root_id);
531 let result = node_mut.get_extension(&ext_identifier);
532
533 assert!(result.is_some());
534 let ext_node_mut = result.unwrap();
535 assert_eq!(ext_node_mut.node_id, ext_node_id);
536 }
537
538 #[test]
539 fn test_node_mut_get_extension_missing() {
540 let mut doc = EureDocument::new();
541 let root_id = doc.get_root_id();
542 let ext_identifier = identifier("nonexistent");
543
544 let node_mut = NodeMut::new(&mut doc, root_id);
546 let result = node_mut.get_extension(&ext_identifier);
547
548 assert!(result.is_none());
549 }
550
551 #[test]
552 fn test_node_mut_debug_valid_node() {
553 let mut doc = EureDocument::new();
554 let root_id = doc.get_root_id();
555
556 let node_mut = NodeMut::new(&mut doc, root_id);
558 let debug_output = alloc::format!("{:?}", node_mut);
559
560 assert!(debug_output.contains("NodeMut"));
562 assert!(debug_output.contains("NodeId"));
563 assert!(debug_output.contains("Node"));
564 assert!(debug_output.contains("Hole"));
565 }
566
567 #[test]
568 fn test_node_mut_debug_invalid_node() {
569 let mut doc = EureDocument::new();
570 let invalid_id = NodeId(999999); let node_mut = NodeMut::new(&mut doc, invalid_id);
574 let debug_output = alloc::format!("{:?}", node_mut);
575
576 assert!(debug_output.contains("NodeMut"));
578 assert!(debug_output.contains("<invalid>"));
579 }
580
581 #[test]
586 fn test_node_value_hole_is_hole() {
587 let value = NodeValue::hole();
588 assert!(value.is_hole());
589 assert_eq!(value, NodeValue::Hole(None));
590 }
591
592 #[test]
593 fn test_empty_containers_are_empty() {
594 let map = NodeValue::empty_map();
595 let array = NodeValue::empty_array();
596 let tuple = NodeValue::empty_tuple();
597
598 if let NodeValue::Map(m) = map {
599 assert!(m.is_empty());
600 } else {
601 panic!("empty_map should create Map");
602 }
603
604 if let NodeValue::Array(a) = array {
605 assert!(a.is_empty());
606 } else {
607 panic!("empty_array should create Array");
608 }
609
610 if let NodeValue::Tuple(t) = tuple {
611 assert!(t.is_empty());
612 } else {
613 panic!("empty_tuple should create Tuple");
614 }
615 }
616
617 #[test]
618 fn test_value_kind_correct() {
619 use crate::value::ValueKind;
620
621 let hole = NodeValue::hole();
622 assert_eq!(hole.value_kind(), ValueKind::Hole);
623
624 let primitive = NodeValue::Primitive(PrimitiveValue::Null);
625 assert_eq!(primitive.value_kind(), ValueKind::Null);
626
627 let bool_val = NodeValue::Primitive(PrimitiveValue::Bool(true));
628 assert_eq!(bool_val.value_kind(), ValueKind::Bool);
629
630 let array = NodeValue::empty_array();
631 assert_eq!(array.value_kind(), ValueKind::Array);
632
633 let map = NodeValue::empty_map();
634 assert_eq!(map.value_kind(), ValueKind::Map);
635
636 let tuple = NodeValue::empty_tuple();
637 assert_eq!(tuple.value_kind(), ValueKind::Tuple);
638 }
639
640 #[test]
641 fn test_require_map_idempotent() {
642 let mut node = Node {
643 content: NodeValue::empty_map(),
644 extensions: Map::new(),
645 };
646
647 for _ in 0..5 {
648 let result = node.require_map();
649 assert!(result.is_ok());
650 }
651
652 assert!(node.as_map().is_some());
653 }
654
655 #[test]
656 fn test_require_array_idempotent() {
657 let mut node = Node {
658 content: NodeValue::empty_array(),
659 extensions: Map::new(),
660 };
661
662 for _ in 0..5 {
663 let result = node.require_array();
664 assert!(result.is_ok());
665 }
666
667 assert!(node.as_array().is_some());
668 }
669
670 #[test]
671 fn test_require_tuple_idempotent() {
672 let mut node = Node {
673 content: NodeValue::empty_tuple(),
674 extensions: Map::new(),
675 };
676
677 for _ in 0..5 {
678 let result = node.require_tuple();
679 assert!(result.is_ok());
680 }
681
682 assert!(node.as_tuple().is_some());
683 }
684
685 #[test]
686 fn test_require_methods_type_mismatch() {
687 let mut array_node = Node {
689 content: NodeValue::empty_array(),
690 extensions: Map::new(),
691 };
692 assert_eq!(
693 array_node.require_map().err(),
694 Some(InsertErrorKind::ExpectedMap)
695 );
696 assert_eq!(
697 array_node.require_tuple().err(),
698 Some(InsertErrorKind::ExpectedTuple)
699 );
700
701 let mut map_node = Node {
703 content: NodeValue::empty_map(),
704 extensions: Map::new(),
705 };
706 assert_eq!(
707 map_node.require_array().err(),
708 Some(InsertErrorKind::ExpectedArray)
709 );
710 assert_eq!(
711 map_node.require_tuple().err(),
712 Some(InsertErrorKind::ExpectedTuple)
713 );
714
715 let mut tuple_node = Node {
717 content: NodeValue::empty_tuple(),
718 extensions: Map::new(),
719 };
720 assert_eq!(
721 tuple_node.require_map().err(),
722 Some(InsertErrorKind::ExpectedMap)
723 );
724 assert_eq!(
725 tuple_node.require_array().err(),
726 Some(InsertErrorKind::ExpectedArray)
727 );
728 }
729}
730
731#[cfg(test)]
732mod proptests {
733 extern crate std;
734
735 use super::*;
736 use proptest::prelude::*;
737 use std::vec::Vec;
738
739 proptest! {
744 #[test]
747 fn array_add_at_zero_on_empty_succeeds(_dummy in Just(())) {
748 let mut array = NodeArray::new();
749 let result = array.add_at(0, NodeId(1));
750 prop_assert!(result.is_ok(), "add_at(0) on empty array should succeed");
751 prop_assert_eq!(array.len(), 1);
752 }
753
754 #[test]
756 fn array_add_at_wrong_index_fails(index in 1usize..100) {
757 let mut array = NodeArray::new();
758
759 let result = array.add_at(index, NodeId(1));
760 prop_assert!(result.is_err(), "add_at({}) on empty array should fail", index);
761
762 match result {
763 Err(InsertErrorKind::ArrayIndexInvalid { index: i, expected_index }) => {
764 prop_assert_eq!(i, index);
765 prop_assert_eq!(expected_index, 0);
766 }
767 other => prop_assert!(false, "Expected ArrayIndexInvalid, got {:?}", other),
768 }
769 }
770
771 #[test]
773 fn array_sequential_add_succeeds(count in 1usize..50) {
774 let mut array = NodeArray::new();
775
776 for i in 0..count {
777 let result = array.add_at(i, NodeId(i));
778 prop_assert!(result.is_ok(), "add_at({}) should succeed", i);
779 }
780
781 prop_assert_eq!(array.len(), count);
782 }
783
784 #[test]
786 fn array_skip_index_fails(
787 fill_count in 0usize..10,
788 skip_amount in 1usize..10,
789 ) {
790 let mut array = NodeArray::new();
791
792 for i in 0..fill_count {
794 array.add_at(i, NodeId(i)).expect("Sequential add failed");
795 }
796
797 let bad_index = fill_count + skip_amount;
799 let result = array.add_at(bad_index, NodeId(bad_index));
800
801 match result {
802 Err(InsertErrorKind::ArrayIndexInvalid { index, expected_index }) => {
803 prop_assert_eq!(index, bad_index);
804 prop_assert_eq!(expected_index, fill_count);
805 }
806 other => prop_assert!(false, "Expected ArrayIndexInvalid, got {:?}", other),
807 }
808 }
809
810 #[test]
812 fn array_push_always_succeeds(count in 1usize..50) {
813 let mut array = NodeArray::new();
814
815 for i in 0..count {
816 let result = array.push(NodeId(i));
817 prop_assert!(result.is_ok(), "push should always succeed");
818 prop_assert_eq!(array.len(), i + 1);
819 }
820 }
821
822 #[test]
824 fn array_get_returns_correct_values(count in 1usize..20) {
825 let mut array = NodeArray::new();
826 let mut expected = Vec::new();
827
828 for i in 0..count {
829 let node_id = NodeId(i * 10); array.push(node_id).unwrap();
831 expected.push(node_id);
832 }
833
834 for (i, &expected_id) in expected.iter().enumerate() {
835 prop_assert_eq!(array.get(i), Some(expected_id),
836 "get({}) should return {:?}", i, expected_id);
837 }
838
839 prop_assert_eq!(array.get(count), None);
841 prop_assert_eq!(array.get(count + 100), None);
842 }
843
844 #[test]
846 fn array_to_vec_preserves_order(count in 0usize..20) {
847 let mut array = NodeArray::new();
848 let mut expected = Vec::new();
849
850 for i in 0..count {
851 let node_id = NodeId(i);
852 array.push(node_id).unwrap();
853 expected.push(node_id);
854 }
855
856 prop_assert_eq!(array.to_vec(), expected);
857 }
858
859 #[test]
861 fn array_from_vec_roundtrip(ids in proptest::collection::vec(0usize..1000, 0..20)) {
862 let node_ids: Vec<NodeId> = ids.iter().map(|&i| NodeId(i)).collect();
863 let array = NodeArray::from_vec(node_ids.clone());
864
865 prop_assert_eq!(array.len(), node_ids.len());
866 prop_assert_eq!(array.to_vec(), node_ids);
867 }
868 }
869
870 proptest! {
875 #[test]
878 fn tuple_add_at_zero_on_empty_succeeds(_dummy in Just(())) {
879 let mut tuple = NodeTuple::new();
880 let result = tuple.add_at(0, NodeId(1));
881 prop_assert!(result.is_ok(), "add_at(0) on empty tuple should succeed");
882 prop_assert_eq!(tuple.len(), 1);
883 }
884
885 #[test]
887 fn tuple_add_at_wrong_index_fails(index in 1u8..100) {
888 let mut tuple = NodeTuple::new();
889
890 let result = tuple.add_at(index, NodeId(1));
891 prop_assert!(result.is_err(), "add_at({}) on empty tuple should fail", index);
892
893 match result {
894 Err(InsertErrorKind::TupleIndexInvalid { index: i, expected_index }) => {
895 prop_assert_eq!(i, index);
896 prop_assert_eq!(expected_index, 0);
897 }
898 other => prop_assert!(false, "Expected TupleIndexInvalid, got {:?}", other),
899 }
900 }
901
902 #[test]
904 fn tuple_sequential_add_succeeds(count in 1u8..50) {
905 let mut tuple = NodeTuple::new();
906
907 for i in 0..count {
908 let result = tuple.add_at(i, NodeId(i as usize));
909 prop_assert!(result.is_ok(), "add_at({}) should succeed", i);
910 }
911
912 prop_assert_eq!(tuple.len(), count as usize);
913 }
914
915 #[test]
917 fn tuple_skip_index_fails(
918 fill_count in 0u8..10,
919 skip_amount in 1u8..10,
920 ) {
921 let mut tuple = NodeTuple::new();
922
923 for i in 0..fill_count {
925 tuple.add_at(i, NodeId(i as usize)).expect("Sequential add failed");
926 }
927
928 let bad_index = fill_count + skip_amount;
930 let result = tuple.add_at(bad_index, NodeId(bad_index as usize));
931
932 match result {
933 Err(InsertErrorKind::TupleIndexInvalid { index, expected_index }) => {
934 prop_assert_eq!(index, bad_index);
935 prop_assert_eq!(expected_index, fill_count as usize);
936 }
937 other => prop_assert!(false, "Expected TupleIndexInvalid, got {:?}", other),
938 }
939 }
940
941 #[test]
943 fn tuple_push_always_succeeds(count in 1usize..50) {
944 let mut tuple = NodeTuple::new();
945
946 for i in 0..count {
947 let result = tuple.push(NodeId(i));
948 prop_assert!(result.is_ok(), "push should always succeed");
949 prop_assert_eq!(tuple.len(), i + 1);
950 }
951 }
952
953 #[test]
955 fn tuple_get_returns_correct_values(count in 1usize..20) {
956 let mut tuple = NodeTuple::new();
957 let mut expected = Vec::new();
958
959 for i in 0..count {
960 let node_id = NodeId(i * 10);
961 tuple.push(node_id).unwrap();
962 expected.push(node_id);
963 }
964
965 for (i, &expected_id) in expected.iter().enumerate() {
966 prop_assert_eq!(tuple.get(i), Some(expected_id),
967 "get({}) should return {:?}", i, expected_id);
968 }
969
970 prop_assert_eq!(tuple.get(count), None);
972 prop_assert_eq!(tuple.get(count + 100), None);
973 }
974
975 #[test]
977 fn tuple_to_vec_preserves_order(count in 0usize..20) {
978 let mut tuple = NodeTuple::new();
979 let mut expected = Vec::new();
980
981 for i in 0..count {
982 let node_id = NodeId(i);
983 tuple.push(node_id).unwrap();
984 expected.push(node_id);
985 }
986
987 prop_assert_eq!(tuple.to_vec(), expected);
988 }
989
990 #[test]
992 fn tuple_from_vec_roundtrip(ids in proptest::collection::vec(0usize..1000, 0..20)) {
993 let node_ids: Vec<NodeId> = ids.iter().map(|&i| NodeId(i)).collect();
994 let tuple = NodeTuple::from_vec(node_ids.clone());
995
996 prop_assert_eq!(tuple.len(), node_ids.len());
997 prop_assert_eq!(tuple.to_vec(), node_ids);
998 }
999 }
1000
1001 proptest! {
1006 #[test]
1008 fn node_value_labeled_hole_preserves_label(label in "[a-z][a-z0-9_-]{0,10}") {
1009 let identifier: Identifier = label.parse().unwrap();
1010 let value = NodeValue::labeled_hole(identifier.clone());
1011
1012 prop_assert!(value.is_hole());
1013 prop_assert_eq!(value, NodeValue::Hole(Some(identifier)));
1014 }
1015 }
1016}