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