1use crate::Value;
2
3macro_rules! implpartialeq {
4 ($($t:ty),+ $(,)?) => {
5 $(
6 impl PartialEq<$t> for Value {
7 #[inline]
8 fn eq(&self, other: &$t) -> bool {
9 if let Some(i) = self.as_integer::<$t>() {
10 &i == other
11 } else {
12 false
13 }
14 }
15 }
16
17 impl PartialEq<$t> for &Value {
18 #[inline]
19 fn eq(&self, other: &$t) -> bool {
20 if let Some(i) = self.as_integer::<$t>() {
21 &i == other
22 } else {
23 false
24 }
25 }
26 }
27 )+
28 };
29}
30
31implpartialeq! {
32 u128,
33 u64,
34 u32,
35 u16,
36 u8,
37 i128,
38 i64,
39 i32,
40 i16,
41 i8,
42}
43
44impl PartialEq<String> for Value {
45 #[inline]
46 fn eq(&self, other: &String) -> bool {
47 if let Some(i) = self.as_text() {
48 i == other
49 } else {
50 false
51 }
52 }
53}
54
55impl PartialEq<String> for &Value {
56 #[inline]
57 fn eq(&self, other: &String) -> bool {
58 if let Some(i) = self.as_str() {
59 i == other
60 } else {
61 false
62 }
63 }
64}
65
66impl PartialEq<&str> for Value {
67 #[inline]
68 fn eq(&self, other: &&str) -> bool {
69 if let Some(i) = self.as_str() {
70 &i == other
71 } else {
72 false
73 }
74 }
75}
76
77impl PartialEq<&str> for &Value {
78 #[inline]
79 fn eq(&self, other: &&str) -> bool {
80 if let Some(i) = self.as_str() {
81 &i == other
82 } else {
83 false
84 }
85 }
86}
87
88impl PartialEq<f64> for Value {
89 #[inline]
90 fn eq(&self, other: &f64) -> bool {
91 if let Some(i) = self.as_float() {
92 &i == other
93 } else {
94 false
95 }
96 }
97}
98
99impl PartialEq<f64> for &Value {
100 #[inline]
101 fn eq(&self, other: &f64) -> bool {
102 if let Some(i) = self.as_float() {
103 &i == other
104 } else {
105 false
106 }
107 }
108}
109
110impl PartialEq<Vec<u8>> for Value {
111 #[inline]
112 fn eq(&self, other: &Vec<u8>) -> bool {
113 self.as_bytes_slice() == Ok(other.as_slice())
114 }
115}
116impl PartialEq<Vec<u8>> for &Value {
117 #[inline]
118 fn eq(&self, other: &Vec<u8>) -> bool {
119 self.as_bytes_slice() == Ok(other.as_slice())
120 }
121}
122
123macro_rules! impl_bytes_array_eq {
124 ($($n:expr),+ $(,)?) => {$(
125 impl PartialEq<[u8; $n]> for Value {
126 #[inline]
127 fn eq(&self, other: &[u8; $n]) -> bool {
128 self.as_bytes_slice() == Ok(other.as_slice())
129 }
130 }
131 impl PartialEq<[u8; $n]> for &Value {
132 #[inline]
133 fn eq(&self, other: &[u8; $n]) -> bool {
134 self.as_bytes_slice() == Ok(other.as_slice())
135 }
136 }
137 )+};
138}
139impl_bytes_array_eq! { 20, 32, 36 }
140
141impl Value {
142 pub fn equal_underlying_data(&self, other: &Value) -> bool {
170 if let (Ok(a), Ok(b)) = (self.as_bytes_slice(), other.as_bytes_slice()) {
172 return a == b;
173 }
174
175 if let (Some(a), Some(b)) = (self.as_i128_unified(), other.as_i128_unified()) {
177 return a == b;
178 }
179
180 match (self, other) {
182 (Value::Map(this), Value::Map(that)) => {
183 if this.len() != that.len() {
184 return false;
185 }
186 let mut consumed = vec![false; that.len()];
190 for (key, value) in this {
191 let matched =
192 that.iter()
193 .enumerate()
194 .find(|(index, (other_key, other_value))| {
195 !consumed[*index]
196 && key.equal_underlying_data(other_key)
197 && value.equal_underlying_data(other_value)
198 });
199 match matched {
200 Some((index, _)) => consumed[index] = true,
201 None => return false,
202 }
203 }
204 true
205 }
206 (Value::Array(this), Value::Array(that)) => {
207 this.len() == that.len()
208 && this
209 .iter()
210 .zip(that)
211 .all(|(value, other_value)| value.equal_underlying_data(other_value))
212 }
213 _ => self == other,
215 }
216 }
217
218 pub fn same_scalar_data(&self, other: &Value) -> bool {
261 fn held_bytes(value: &Value) -> Option<Vec<u8>> {
264 match value {
265 Value::Array(items) => items
266 .iter()
267 .map(|item| match item {
268 Value::U8(byte) => Some(*byte),
269 _ => None,
270 })
271 .collect(),
272 _ => value.as_bytes_slice().ok().map(<[u8]>::to_vec),
273 }
274 }
275
276 match (self, other) {
277 (Value::Array(_), _) | (_, Value::Array(_)) => matches!(
279 (held_bytes(self), held_bytes(other)),
280 (Some(this), Some(that)) if this == that
281 ),
282 (Value::Map(_), _) | (_, Value::Map(_)) => false,
284 (Value::Float(_), _) | (_, Value::Float(_)) => matches!(
286 (self.as_float(), other.as_float()),
287 (Some(this), Some(that)) if this.to_bits() == that.to_bits()
288 ),
289 _ => self.equal_underlying_data(other),
291 }
292 }
293}
294
295#[cfg(test)]
296mod underlying_data_tests {
297 use crate::Value;
298
299 fn map(entries: Vec<(&str, Value)>) -> Value {
300 Value::Map(
301 entries
302 .into_iter()
303 .map(|(key, value)| (Value::Text(key.to_string()), value))
304 .collect(),
305 )
306 }
307
308 #[test]
312 fn maps_compare_equal_across_member_order_and_integer_width() {
313 let sent = map(vec![
314 ("rank", Value::U64(7)),
315 ("tag", Value::Text("intro".into())),
316 ]);
317 let stored = map(vec![
318 ("tag", Value::Text("intro".into())),
319 ("rank", Value::U8(7)),
320 ]);
321
322 assert!(sent.equal_underlying_data(&stored));
323 assert!(stored.equal_underlying_data(&sent));
324 }
325
326 #[test]
327 fn maps_differ_on_a_changed_nested_value() {
328 let before = map(vec![
329 ("rank", Value::U64(7)),
330 ("tag", Value::Text("intro".into())),
331 ]);
332 let after = map(vec![
333 ("tag", Value::Text("intro".into())),
334 ("rank", Value::U8(8)),
335 ]);
336
337 assert!(!before.equal_underlying_data(&after));
338 }
339
340 #[test]
341 fn maps_differ_on_a_missing_or_extra_member() {
342 let one = map(vec![("tag", Value::Text("intro".into()))]);
343 let two = map(vec![
344 ("tag", Value::Text("intro".into())),
345 ("rank", Value::U8(7)),
346 ]);
347
348 assert!(!one.equal_underlying_data(&two));
349 assert!(!two.equal_underlying_data(&one));
350 }
351
352 #[test]
353 fn nested_maps_recurse() {
354 let sent = map(vec![(
355 "meta",
356 map(vec![
357 ("rank", Value::I64(7)),
358 ("tag", Value::Text("a".into())),
359 ]),
360 )]);
361 let stored = map(vec![(
362 "meta",
363 map(vec![
364 ("tag", Value::Text("a".into())),
365 ("rank", Value::U8(7)),
366 ]),
367 )]);
368
369 assert!(sent.equal_underlying_data(&stored));
370 }
371
372 #[test]
373 fn arrays_compare_position_by_position_with_integer_leniency() {
374 let sent = Value::Array(vec![Value::U64(1), Value::U64(2)]);
375 let stored = Value::Array(vec![Value::U8(1), Value::U8(2)]);
376 let reordered = Value::Array(vec![Value::U8(2), Value::U8(1)]);
377 let shorter = Value::Array(vec![Value::U8(1)]);
378
379 assert!(sent.equal_underlying_data(&stored));
380 assert!(!sent.equal_underlying_data(&reordered));
381 assert!(!sent.equal_underlying_data(&shorter));
382 }
383
384 #[test]
388 fn maps_match_entries_one_to_one() {
389 let doubled = map(vec![("tag", Value::U8(1)), ("tag", Value::U8(1))]);
390 let single_plus_other = map(vec![("tag", Value::U8(1)), ("rank", Value::U8(1))]);
391 let doubled_too = map(vec![("tag", Value::U64(1)), ("tag", Value::U64(1))]);
392
393 assert!(!doubled.equal_underlying_data(&single_plus_other));
394 assert!(!single_plus_other.equal_underlying_data(&doubled));
395 assert!(doubled.equal_underlying_data(&doubled_too));
396 }
397
398 #[test]
399 fn a_map_never_equals_a_non_map() {
400 let a_map = map(vec![("tag", Value::Text("a".into()))]);
401
402 assert!(!a_map.equal_underlying_data(&Value::Text("a".into())));
403 assert!(!a_map.equal_underlying_data(&Value::Array(vec![])));
404 }
405}
406
407#[cfg(test)]
408mod same_scalar_data_tests {
409 use crate::Value;
410
411 fn same(left: &Value, right: &Value) -> bool {
413 let forward = left.same_scalar_data(right);
414 assert_eq!(
415 forward,
416 right.same_scalar_data(left),
417 "{left:?} and {right:?} compare differently each way"
418 );
419 forward
420 }
421
422 #[test]
424 fn should_not_equate_the_empty_string_with_a_nul_character() {
425 let empty = Value::Text(String::new());
426 let nul = Value::Text("\0".to_string());
427
428 assert!(!same(&empty, &nul));
429 assert!(same(&empty, &empty.clone()));
430 assert!(same(&nul, &nul.clone()));
431 }
432
433 #[test]
436 fn should_equate_the_same_integer_carried_at_different_widths() {
437 assert!(same(&Value::U64(513), &Value::U16(513)));
438 assert!(same(&Value::I64(-7), &Value::I32(-7)));
439 assert!(same(&Value::U8(100), &Value::I128(100)));
440 assert!(!same(&Value::U64(514), &Value::U16(513)));
441 assert!(!same(&Value::I8(-1), &Value::U64(255)));
442 }
443
444 #[test]
445 fn should_equate_a_u128_past_i128_only_with_the_same_u128() {
446 let past_i128 = u128::MAX;
447
448 assert!(same(&Value::U128(past_i128), &Value::U128(past_i128)));
449 assert!(!same(&Value::U128(past_i128), &Value::U128(past_i128 - 1)));
450 assert!(!same(
451 &Value::U128(i128::MAX as u128 + 1),
452 &Value::I128(i128::MAX)
453 ));
454 assert!(!same(&Value::U128(past_i128), &Value::U64(u64::MAX)));
455 assert!(same(
456 &Value::U128(i128::MAX as u128),
457 &Value::I128(i128::MAX)
458 ));
459 }
460
461 #[test]
462 fn should_equate_an_identifier_with_the_same_32_bytes() {
463 let id = [7u8; 32];
464
465 assert!(same(&Value::Identifier(id), &Value::Bytes32(id)));
466 assert!(same(&Value::Bytes(id.to_vec()), &Value::Identifier(id)));
467 assert!(!same(&Value::Identifier(id), &Value::Identifier([8u8; 32])));
468 assert!(!same(&Value::Identifier(id), &Value::Bytes(vec![7u8; 31])));
469 }
470
471 #[test]
473 fn should_equate_equal_strings_and_byte_arrays_longer_than_a_tree_key() {
474 let long_ascii = Value::Text("a".repeat(256));
475 let long_emoji = Value::Text("\u{1F600}".repeat(70));
477
478 assert!(same(&long_ascii, &long_ascii.clone()));
479 assert!(same(&long_emoji, &long_emoji.clone()));
480 assert!(!same(&long_ascii, &Value::Text("a".repeat(257))));
481 assert!(same(
482 &Value::Bytes(vec![9; 300]),
483 &Value::Bytes(vec![9; 300])
484 ));
485 assert!(!same(
486 &Value::Bytes(vec![9; 300]),
487 &Value::Bytes(vec![9; 301])
488 ));
489 }
490
491 #[test]
494 fn should_compare_floats_by_their_bits() {
495 let quiet_nan = Value::Float(f64::NAN);
496 let other_nan = Value::Float(f64::from_bits(f64::NAN.to_bits() | 1));
497
498 assert!(!same(&Value::Float(-0.0), &Value::Float(0.0)));
499 assert!(Value::Float(-0.0).equal_underlying_data(&Value::Float(0.0)));
500 assert!(same(&Value::Float(1.5), &Value::Float(1.5)));
501 assert!(!same(&Value::Float(1.5), &Value::Float(2.5)));
502 assert!(same(&quiet_nan, &quiet_nan.clone()));
503 assert!(!quiet_nan.equal_underlying_data(&quiet_nan.clone()));
504 assert!(!same(&quiet_nan, &other_nan));
505 }
506
507 #[test]
510 fn should_read_an_integer_against_a_float_as_the_float_it_converts_to() {
511 assert!(same(&Value::U64(1_700_000_000_000), &Value::Float(1.7e12)));
512 assert!(!same(&Value::U64(1_700_000_000_001), &Value::Float(1.7e12)));
513 assert!(same(&Value::I32(-3), &Value::Float(-3.0)));
514 assert!(same(&Value::U64(0), &Value::Float(0.0)));
515 assert!(!same(&Value::U64(0), &Value::Float(-0.0)));
516 assert!(!same(&Value::Text("1".to_string()), &Value::Float(1.0)));
517 assert!(!same(&Value::Bool(true), &Value::Float(1.0)));
518 }
519
520 #[test]
523 fn should_round_an_integer_past_2_pow_53_to_the_nearest_float() {
524 let two_pow_53 = 1u64 << 53;
525 let float_two_pow_53 = Value::Float(two_pow_53 as f64);
526
527 assert!(same(&Value::U64(two_pow_53 + 1), &float_two_pow_53));
528 assert!(same(&Value::U64(two_pow_53), &float_two_pow_53));
529 assert!(!same(&Value::U64(two_pow_53 + 1), &Value::U64(two_pow_53)));
530
531 assert!(same(
532 &Value::I128(i128::MIN),
533 &Value::Float(-(2.0f64.powi(127)))
534 ));
535 assert!(same(
536 &Value::U128(u128::MAX),
537 &Value::Float(2.0f64.powi(128))
538 ));
539 assert!(!same(&Value::U128(u128::MAX), &Value::Float(f64::INFINITY)));
540 }
541
542 #[test]
543 fn should_never_equate_a_map_or_an_array_of_anything_but_bytes() {
544 let empty_map = Value::Map(vec![]);
545 let one_entry_map = Value::Map(vec![(Value::Text("a".into()), Value::U8(1))]);
546 let wide_integers = Value::Array(vec![Value::U64(1), Value::U64(2)]);
547 let texts = Value::Array(vec![Value::Text("a".into())]);
548
549 assert!(!same(&empty_map, &empty_map.clone()));
550 assert!(!same(&one_entry_map, &one_entry_map.clone()));
551 assert!(one_entry_map.equal_underlying_data(&one_entry_map.clone()));
552 assert!(!same(&wide_integers, &wide_integers.clone()));
553 assert!(!same(&wide_integers, &Value::Bytes(vec![1, 2])));
554 assert!(!same(&texts, &texts.clone()));
555 assert!(!same(&empty_map, &Value::Null));
556 assert!(!same(&empty_map, &Value::Array(vec![])));
557 }
558
559 #[test]
562 fn should_read_an_array_of_u8_as_the_bytes_it_lists() {
563 let id = [7u8; 32];
564 let listed = Value::Array(id.iter().copied().map(Value::U8).collect());
565
566 assert!(same(&listed, &Value::Identifier(id)));
567 assert!(same(&listed, &Value::Bytes32(id)));
568 assert!(same(&listed, &Value::Bytes(id.to_vec())));
569 assert!(same(&listed, &listed.clone()));
570 assert!(same(&Value::Array(vec![]), &Value::Bytes(vec![])));
571 assert!(!same(&listed, &Value::Identifier([8u8; 32])));
572 assert!(!same(&Value::Array(vec![Value::U8(1)]), &Value::Float(1.0)));
573 assert!(!same(&Value::Array(vec![Value::U8(1)]), &Value::U8(1)));
574 assert!(!same(
575 &Value::Array(vec![Value::U8(97)]),
576 &Value::Text("a".into())
577 ));
578 assert!(!same(&Value::Array(vec![Value::U8(1)]), &Value::Null));
579 }
580
581 #[test]
582 fn should_equate_two_nulls_and_nothing_else_with_a_null() {
583 assert!(same(&Value::Null, &Value::Null));
584 assert!(!same(&Value::Null, &Value::Text(String::new())));
585 assert!(!same(&Value::Null, &Value::Bytes(vec![])));
586 assert!(!same(&Value::Null, &Value::U64(0)));
587 assert!(!same(&Value::Null, &Value::Bool(false)));
588 assert!(!same(&Value::Null, &Value::Float(0.0)));
589 }
590
591 #[test]
592 fn should_not_equate_values_of_different_kinds() {
593 assert!(!same(&Value::Text("1".to_string()), &Value::U64(1)));
594 assert!(!same(&Value::Bool(true), &Value::U8(1)));
595 assert!(!same(&Value::U64(1), &Value::Bool(true)));
596 assert!(!same(
597 &Value::Text("abc".to_string()),
598 &Value::Bytes(b"abc".to_vec())
599 ));
600 assert!(same(&Value::Bool(true), &Value::Bool(true)));
601 assert!(!same(&Value::Bool(true), &Value::Bool(false)));
602 }
603}
604
605#[cfg(test)]
606#[allow(clippy::approx_constant)]
607mod tests {
608 use crate::Value;
609
610 #[test]
613 fn u8_eq() {
614 assert_eq!(Value::U8(42), 42u8);
615 assert_ne!(Value::U8(42), 43u8);
616 }
617
618 #[test]
619 fn i8_eq() {
620 assert_eq!(Value::I8(-1), -1i8);
621 assert_ne!(Value::I8(-1), 0i8);
622 }
623
624 #[test]
625 fn u16_eq() {
626 assert_eq!(Value::U16(1000), 1000u16);
627 assert_ne!(Value::U16(1000), 999u16);
628 }
629
630 #[test]
631 fn i16_eq() {
632 assert_eq!(Value::I16(-500), -500i16);
633 assert_ne!(Value::I16(-500), 500i16);
634 }
635
636 #[test]
637 fn u32_eq() {
638 assert_eq!(Value::U32(100_000), 100_000u32);
639 assert_ne!(Value::U32(100_000), 0u32);
640 }
641
642 #[test]
643 fn i32_eq() {
644 assert_eq!(Value::I32(-100), -100i32);
645 assert_ne!(Value::I32(-100), 100i32);
646 }
647
648 #[test]
649 fn u64_eq() {
650 assert_eq!(Value::U64(u64::MAX), u64::MAX);
651 assert_ne!(Value::U64(0), 1u64);
652 }
653
654 #[test]
655 fn i64_eq() {
656 assert_eq!(Value::I64(i64::MIN), i64::MIN);
657 assert_ne!(Value::I64(0), 1i64);
658 }
659
660 #[test]
661 fn u128_eq() {
662 assert_eq!(Value::U128(u128::MAX), u128::MAX);
663 assert_ne!(Value::U128(0), 1u128);
664 }
665
666 #[test]
667 fn i128_eq() {
668 assert_eq!(Value::I128(i128::MIN), i128::MIN);
669 assert_ne!(Value::I128(0), 1i128);
670 }
671
672 #[test]
675 fn u8_value_eq_u64_type() {
676 assert_eq!(Value::U8(10), 10u64);
678 }
679
680 #[test]
681 fn u64_value_eq_u8_type_when_fits() {
682 assert_eq!(Value::U64(200), 200u8);
683 }
684
685 #[test]
686 fn u64_value_ne_u8_type_when_overflow() {
687 assert_ne!(Value::U64(256), 0u8); }
690
691 #[test]
692 fn i8_value_eq_i64_type() {
693 assert_eq!(Value::I8(-10), -10i64);
694 }
695
696 #[test]
697 fn non_integer_ne_integer() {
698 assert_ne!(Value::Text("hello".to_string()), 0u64);
699 assert_ne!(Value::Null, 0i32);
700 assert_ne!(Value::Bool(true), 1u8);
701 }
702
703 #[test]
706 fn string_eq() {
707 let val = Value::Text("hello".to_string());
708 assert_eq!(val, "hello".to_string());
709 assert_ne!(val, "world".to_string());
710 }
711
712 #[test]
713 fn non_text_ne_string() {
714 assert_ne!(Value::U8(0), "0".to_string());
715 assert_ne!(Value::Null, "".to_string());
716 }
717
718 #[test]
721 fn str_ref_eq() {
722 let val = Value::Text("test".to_string());
723 assert_eq!(val, "test");
724 assert_ne!(val, "other");
725 }
726
727 #[test]
728 fn non_text_ne_str_ref() {
729 assert_ne!(Value::Bool(false), "false");
730 }
731
732 #[test]
735 fn float_eq() {
736 assert_eq!(Value::Float(3.14), 3.14f64);
737 assert_ne!(Value::Float(3.14), 3.15f64);
738 }
739
740 #[test]
741 fn integer_eq_float_through_as_float() {
742 assert_eq!(Value::U64(10), 10.0f64);
744 }
745
746 #[test]
747 fn non_numeric_ne_float() {
748 assert_ne!(Value::Text("3.14".to_string()), 3.14f64);
749 }
750
751 #[test]
754 fn bytes_eq_vec_u8() {
755 let data = vec![1, 2, 3];
756 assert_eq!(Value::Bytes(data.clone()), data);
757 }
758
759 #[test]
760 fn bytes_ne_vec_u8() {
761 assert_ne!(Value::Bytes(vec![1, 2, 3]), vec![1, 2, 4]);
762 }
763
764 #[test]
765 fn identifier_eq_vec_u8() {
766 let id = [42u8; 32];
767 assert_eq!(Value::Identifier(id), id.to_vec());
768 }
769
770 #[test]
771 fn bytes20_eq_vec_u8() {
772 let b = [5u8; 20];
773 assert_eq!(Value::Bytes20(b), b.to_vec());
774 }
775
776 #[test]
777 fn non_bytes_ne_vec_u8() {
778 assert_ne!(Value::U8(1), vec![1u8]);
779 }
780
781 #[test]
784 fn bytes32_eq_array() {
785 let b = [0xffu8; 32];
786 assert_eq!(Value::Bytes32(b), b);
787 }
788
789 #[test]
790 fn identifier_eq_array_32() {
791 let id = [7u8; 32];
792 assert_eq!(Value::Identifier(id), id);
793 }
794
795 #[test]
796 fn bytes_eq_array_32() {
797 let data = [3u8; 32];
798 assert_eq!(Value::Bytes(data.to_vec()), data);
799 }
800
801 #[test]
802 fn non_bytes_ne_array_32() {
803 assert_ne!(Value::Null, [0u8; 32]);
804 }
805
806 #[test]
809 fn bytes20_eq_array_20() {
810 let b = [1u8; 20];
811 assert_eq!(Value::Bytes20(b), b);
812 }
813
814 #[test]
817 fn bytes36_eq_array_36() {
818 let b = [2u8; 36];
819 assert_eq!(Value::Bytes36(b), b);
820 }
821
822 #[test]
825 fn ref_value_eq_integer() {
826 let val = Value::U64(42);
827 assert_eq!(&val, 42u64);
828 }
829
830 #[test]
831 fn ref_value_eq_string() {
832 let val = Value::Text("hi".to_string());
833 assert_eq!(&val, "hi".to_string());
834 }
835
836 #[test]
837 fn ref_value_eq_str_ref() {
838 let val = Value::Text("hi".to_string());
839 assert_eq!(&val, "hi");
840 }
841
842 #[test]
843 fn ref_value_eq_float() {
844 let val = Value::Float(1.0);
845 assert_eq!(&val, 1.0f64);
846 }
847
848 #[test]
849 fn ref_value_eq_vec_u8() {
850 let val = Value::Bytes(vec![10, 20]);
851 assert_eq!(&val, vec![10u8, 20]);
852 }
853
854 #[test]
855 fn ref_value_eq_array_32() {
856 let b = [0u8; 32];
857 let val = Value::Bytes32(b);
858 assert_eq!(&val, b);
859 }
860
861 #[test]
864 fn equal_underlying_data_bytes_vs_identifier_same_data() {
865 let data = [42u8; 32];
866 let bytes = Value::Bytes(data.to_vec());
867 let ident = Value::Identifier(data);
868 assert!(bytes.equal_underlying_data(&ident));
869 assert!(ident.equal_underlying_data(&bytes));
870 }
871
872 #[test]
873 fn equal_underlying_data_bytes_vs_identifier_different_data() {
874 let bytes = Value::Bytes(vec![0u8; 32]);
875 let ident = Value::Identifier([1u8; 32]);
876 assert!(!bytes.equal_underlying_data(&ident));
877 }
878
879 #[test]
880 fn equal_underlying_data_bytes32_vs_identifier() {
881 let data = [99u8; 32];
882 let b32 = Value::Bytes32(data);
883 let ident = Value::Identifier(data);
884 assert!(b32.equal_underlying_data(&ident));
885 }
886
887 #[test]
888 fn equal_underlying_data_bytes20_vs_bytes() {
889 let data = [5u8; 20];
890 let b20 = Value::Bytes20(data);
891 let bytes = Value::Bytes(data.to_vec());
892 assert!(b20.equal_underlying_data(&bytes));
893 }
894
895 #[test]
896 fn equal_underlying_data_u8_vs_u64_same_value() {
897 let a = Value::U8(10);
898 let b = Value::U64(10);
899 assert!(a.equal_underlying_data(&b));
900 }
901
902 #[test]
903 fn equal_underlying_data_i8_vs_i128_same_value() {
904 let a = Value::I8(-5);
905 let b = Value::I128(-5);
906 assert!(a.equal_underlying_data(&b));
907 }
908
909 #[test]
910 fn equal_underlying_data_u8_vs_u64_different_value() {
911 let a = Value::U8(10);
912 let b = Value::U64(20);
913 assert!(!a.equal_underlying_data(&b));
914 }
915
916 #[test]
917 fn equal_underlying_data_u16_vs_i32_same_value() {
918 let a = Value::U16(100);
919 let b = Value::I32(100);
920 assert!(a.equal_underlying_data(&b));
921 }
922
923 #[test]
924 fn equal_underlying_data_negative_i8_vs_u64() {
925 let a = Value::I8(-1);
927 let b = Value::U64(255);
928 assert!(!a.equal_underlying_data(&b));
929 }
930
931 #[test]
932 fn equal_underlying_data_same_variant_same_value() {
933 let a = Value::U64(42);
934 let b = Value::U64(42);
935 assert!(a.equal_underlying_data(&b));
936 }
937
938 #[test]
939 fn equal_underlying_data_fallback_to_partial_eq() {
940 let a = Value::Text("hello".to_string());
942 let b = Value::Text("hello".to_string());
943 assert!(a.equal_underlying_data(&b));
944
945 let c = Value::Text("world".to_string());
946 assert!(!a.equal_underlying_data(&c));
947 }
948
949 #[test]
950 fn equal_underlying_data_null_vs_null() {
951 assert!(Value::Null.equal_underlying_data(&Value::Null));
952 }
953
954 #[test]
955 fn equal_underlying_data_different_types_not_equal() {
956 let a = Value::Text("42".to_string());
958 let b = Value::U64(42);
959 assert!(!a.equal_underlying_data(&b));
960 }
961
962 #[test]
963 fn equal_underlying_data_bool_vs_bool() {
964 assert!(Value::Bool(true).equal_underlying_data(&Value::Bool(true)));
965 assert!(!Value::Bool(true).equal_underlying_data(&Value::Bool(false)));
966 }
967
968 #[test]
969 fn equal_underlying_data_float_vs_float() {
970 assert!(Value::Float(1.5).equal_underlying_data(&Value::Float(1.5)));
971 assert!(!Value::Float(1.5).equal_underlying_data(&Value::Float(2.5)));
972 }
973}