Skip to main content

libmagic_rs/evaluator/operators/
equality.rs

1// Copyright (c) 2025-2026 the libmagic-rs contributors
2// SPDX-License-Identifier: Apache-2.0
3
4//! Equality and inequality operators for magic rule evaluation
5
6use std::cmp::Ordering;
7
8use crate::parser::ast::Value;
9
10use super::compare_values;
11
12/// Apply equality comparison between two values
13///
14/// Compares two `Value` instances for equality, handling proper type matching.
15/// Cross-type integer comparisons (`Uint` vs `Int`) are supported via `i128`
16/// coercion. Incompatible types (e.g., string vs integer) are considered unequal.
17///
18/// # Arguments
19///
20/// * `left` - The left-hand side value (typically from file data)
21/// * `right` - The right-hand side value (typically from magic rule)
22///
23/// # Returns
24///
25/// `true` if the values are equal (including cross-type integer coercion), `false` otherwise
26///
27/// # Examples
28///
29/// ```
30/// use libmagic_rs::parser::ast::Value;
31/// use libmagic_rs::evaluator::operators::apply_equal;
32///
33/// // Same type, same value
34/// assert!(apply_equal(&Value::Uint(42), &Value::Uint(42)));
35///
36/// // Same type, different value
37/// assert!(!apply_equal(&Value::Uint(42), &Value::Uint(24)));
38///
39/// // Cross-type integer coercion
40/// assert!(apply_equal(&Value::Uint(42), &Value::Int(42)));
41///
42/// // String comparison
43/// assert!(apply_equal(
44///     &Value::String("hello".to_string()),
45///     &Value::String("hello".to_string())
46/// ));
47/// ```
48#[must_use]
49pub fn apply_equal(left: &Value, right: &Value) -> bool {
50    compare_values(left, right) == Some(Ordering::Equal)
51}
52
53/// Apply inequality comparison between two values
54///
55/// Compares two `Value` instances for inequality, implementing the negation
56/// of equality comparison logic. Returns `true` if the values are not equal
57/// or are of different types.
58///
59/// # Arguments
60///
61/// * `left` - The left-hand side value (typically from file data)
62/// * `right` - The right-hand side value (typically from magic rule)
63///
64/// # Returns
65///
66/// `true` if the values are not equal or of different types, `false` if they are equal
67///
68/// # Examples
69///
70/// ```
71/// use libmagic_rs::parser::ast::Value;
72/// use libmagic_rs::evaluator::operators::apply_not_equal;
73///
74/// // Same type, different value
75/// assert!(apply_not_equal(&Value::Uint(42), &Value::Uint(24)));
76///
77/// // Same type, same value
78/// assert!(!apply_not_equal(&Value::Uint(42), &Value::Uint(42)));
79///
80/// // Cross-type integers with same numeric value (equal via coercion)
81/// assert!(!apply_not_equal(&Value::Uint(42), &Value::Int(42)));
82///
83/// // String comparison
84/// assert!(apply_not_equal(
85///     &Value::String("hello".to_string()),
86///     &Value::String("world".to_string())
87/// ));
88/// ```
89#[must_use]
90pub fn apply_not_equal(left: &Value, right: &Value) -> bool {
91    !apply_equal(left, right)
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_apply_equal_uint_same_value() {
100        let left = Value::Uint(42);
101        let right = Value::Uint(42);
102        assert!(apply_equal(&left, &right));
103    }
104
105    #[test]
106    fn test_apply_equal_uint_different_value() {
107        let left = Value::Uint(42);
108        let right = Value::Uint(24);
109        assert!(!apply_equal(&left, &right));
110    }
111
112    #[test]
113    fn test_apply_equal_uint_zero() {
114        let left = Value::Uint(0);
115        let right = Value::Uint(0);
116        assert!(apply_equal(&left, &right));
117    }
118
119    #[test]
120    fn test_apply_equal_uint_max_value() {
121        let left = Value::Uint(u64::MAX);
122        let right = Value::Uint(u64::MAX);
123        assert!(apply_equal(&left, &right));
124    }
125
126    #[test]
127    fn test_apply_equal_int_same_value() {
128        let left = Value::Int(42);
129        let right = Value::Int(42);
130        assert!(apply_equal(&left, &right));
131    }
132
133    #[test]
134    fn test_apply_equal_int_different_value() {
135        let left = Value::Int(42);
136        let right = Value::Int(-42);
137        assert!(!apply_equal(&left, &right));
138    }
139
140    #[test]
141    fn test_apply_equal_int_negative() {
142        let left = Value::Int(-100);
143        let right = Value::Int(-100);
144        assert!(apply_equal(&left, &right));
145    }
146
147    #[test]
148    fn test_apply_equal_int_zero() {
149        let left = Value::Int(0);
150        let right = Value::Int(0);
151        assert!(apply_equal(&left, &right));
152    }
153
154    #[test]
155    fn test_apply_equal_int_extreme_values() {
156        let left = Value::Int(i64::MAX);
157        let right = Value::Int(i64::MAX);
158        assert!(apply_equal(&left, &right));
159
160        let left = Value::Int(i64::MIN);
161        let right = Value::Int(i64::MIN);
162        assert!(apply_equal(&left, &right));
163    }
164
165    #[test]
166    fn test_apply_equal_bytes_same_value() {
167        let left = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
168        let right = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
169        assert!(apply_equal(&left, &right));
170    }
171
172    #[test]
173    fn test_apply_equal_bytes_different_value() {
174        let left = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
175        let right = Value::Bytes(vec![0x50, 0x4b, 0x03, 0x04]);
176        assert!(!apply_equal(&left, &right));
177    }
178
179    #[test]
180    fn test_apply_equal_bytes_empty() {
181        let left = Value::Bytes(vec![]);
182        let right = Value::Bytes(vec![]);
183        assert!(apply_equal(&left, &right));
184    }
185
186    #[test]
187    fn test_apply_equal_bytes_different_length() {
188        let left = Value::Bytes(vec![0x7f, 0x45]);
189        let right = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
190        assert!(!apply_equal(&left, &right));
191    }
192
193    #[test]
194    fn test_apply_equal_bytes_single_byte() {
195        let left = Value::Bytes(vec![0x7f]);
196        let right = Value::Bytes(vec![0x7f]);
197        assert!(apply_equal(&left, &right));
198
199        let left = Value::Bytes(vec![0x7f]);
200        let right = Value::Bytes(vec![0x45]);
201        assert!(!apply_equal(&left, &right));
202    }
203
204    #[test]
205    fn test_apply_equal_string_same_value() {
206        let left = Value::String("hello".to_string());
207        let right = Value::String("hello".to_string());
208        assert!(apply_equal(&left, &right));
209    }
210
211    #[test]
212    fn test_apply_equal_string_different_value() {
213        let left = Value::String("hello".to_string());
214        let right = Value::String("world".to_string());
215        assert!(!apply_equal(&left, &right));
216    }
217
218    #[test]
219    fn test_apply_equal_string_empty() {
220        let left = Value::String(String::new());
221        let right = Value::String(String::new());
222        assert!(apply_equal(&left, &right));
223    }
224
225    #[test]
226    fn test_apply_equal_string_case_sensitive() {
227        let left = Value::String("Hello".to_string());
228        let right = Value::String("hello".to_string());
229        assert!(!apply_equal(&left, &right));
230    }
231
232    #[test]
233    fn test_apply_equal_string_unicode() {
234        let left = Value::String("\u{1f980} Rust".to_string());
235        let right = Value::String("\u{1f980} Rust".to_string());
236        assert!(apply_equal(&left, &right));
237
238        let left = Value::String("\u{1f980} Rust".to_string());
239        let right = Value::String("\u{1f40d} Python".to_string());
240        assert!(!apply_equal(&left, &right));
241    }
242
243    #[test]
244    fn test_apply_equal_string_whitespace() {
245        let left = Value::String("hello world".to_string());
246        let right = Value::String("hello world".to_string());
247        assert!(apply_equal(&left, &right));
248
249        let left = Value::String("hello world".to_string());
250        let right = Value::String("hello  world".to_string()); // Extra space
251        assert!(!apply_equal(&left, &right));
252    }
253
254    // Cross-type comparison tests (should all return false)
255    #[test]
256    fn test_apply_equal_uint_vs_int() {
257        // Same numeric value across types should match
258        let left = Value::Uint(42);
259        let right = Value::Int(42);
260        assert!(apply_equal(&left, &right));
261
262        let left = Value::Uint(0);
263        let right = Value::Int(0);
264        assert!(apply_equal(&left, &right));
265
266        // Negative Int cannot equal Uint
267        let left = Value::Uint(42);
268        let right = Value::Int(-42);
269        assert!(!apply_equal(&left, &right));
270
271        // Large Uint that doesn't fit in i64 cannot equal Int
272        let left = Value::Uint(u64::MAX);
273        let right = Value::Int(-1);
274        assert!(!apply_equal(&left, &right));
275    }
276
277    #[test]
278    fn test_apply_equal_uint_vs_bytes() {
279        let left = Value::Uint(42);
280        let right = Value::Bytes(vec![42]);
281        assert!(!apply_equal(&left, &right));
282    }
283
284    #[test]
285    fn test_apply_equal_uint_vs_string() {
286        let left = Value::Uint(42);
287        let right = Value::String("42".to_string());
288        assert!(!apply_equal(&left, &right));
289    }
290
291    #[test]
292    fn test_apply_equal_int_vs_bytes() {
293        let left = Value::Int(-42);
294        let right = Value::Bytes(vec![214]); // -42 as u8
295        assert!(!apply_equal(&left, &right));
296    }
297
298    #[test]
299    fn test_apply_equal_int_vs_string() {
300        let left = Value::Int(-42);
301        let right = Value::String("-42".to_string());
302        assert!(!apply_equal(&left, &right));
303    }
304
305    #[test]
306    fn test_apply_equal_bytes_vs_string() {
307        let left = Value::Bytes(vec![104, 101, 108, 108, 111]); // "hello" as bytes
308        let right = Value::String("hello".to_string());
309        assert!(!apply_equal(&left, &right));
310    }
311
312    #[test]
313    fn test_apply_equal_all_cross_type_combinations() {
314        let values = [
315            Value::Uint(42),
316            Value::Int(42),
317            Value::Bytes(vec![42]),
318            Value::String("42".to_string()),
319        ];
320
321        // Test cross-type comparisons
322        for (i, left) in values.iter().enumerate() {
323            for (j, right) in values.iter().enumerate() {
324                if i != j {
325                    let result = apply_equal(left, right);
326                    // Uint(42) and Int(42) should be equal (cross-type coercion)
327                    if (i <= 1) && (j <= 1) {
328                        assert!(
329                            result,
330                            "Integer cross-type comparison should be true: {left:?} vs {right:?}"
331                        );
332                    } else {
333                        assert!(
334                            !result,
335                            "Non-integer cross-type comparison should be false: {left:?} vs {right:?}"
336                        );
337                    }
338                }
339            }
340        }
341    }
342
343    #[test]
344    fn test_apply_equal_reflexivity() {
345        let values = vec![
346            Value::Uint(42),
347            Value::Int(-42),
348            Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
349            Value::String("hello".to_string()),
350        ];
351
352        // Test that all values are equal to themselves
353        for value in values {
354            assert!(
355                apply_equal(&value, &value),
356                "Value should be equal to itself: {value:?}"
357            );
358        }
359    }
360
361    #[test]
362    fn test_apply_equal_symmetry() {
363        let test_cases = vec![
364            (Value::Uint(42), Value::Uint(42)),
365            (Value::Int(-100), Value::Int(-100)),
366            (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![1, 2, 3])),
367            (
368                Value::String("test".to_string()),
369                Value::String("test".to_string()),
370            ),
371        ];
372
373        // Test that equality is symmetric: a == b implies b == a
374        for (left, right) in test_cases {
375            let left_to_right = apply_equal(&left, &right);
376            let right_to_left = apply_equal(&right, &left);
377            assert_eq!(
378                left_to_right, right_to_left,
379                "Equality should be symmetric: {left:?} vs {right:?}"
380            );
381        }
382    }
383
384    #[test]
385    fn test_apply_equal_transitivity() {
386        // Test transitivity: if a == b and b == c, then a == c
387        let a = Value::Uint(123);
388        let b = Value::Uint(123);
389        let c = Value::Uint(123);
390
391        assert!(apply_equal(&a, &b));
392        assert!(apply_equal(&b, &c));
393        assert!(apply_equal(&a, &c));
394    }
395
396    #[test]
397    fn test_apply_equal_edge_cases() {
398        // Test with maximum values
399        let max_unsigned = Value::Uint(u64::MAX);
400        let max_signed = Value::Int(i64::MAX);
401        let min_int = Value::Int(i64::MIN);
402
403        assert!(apply_equal(&max_unsigned, &max_unsigned));
404        assert!(apply_equal(&max_signed, &max_signed));
405        assert!(apply_equal(&min_int, &min_int));
406
407        // Cross-type edge cases
408        // u64::MAX != -1 in i64 (different mathematical values)
409        assert!(!apply_equal(&max_unsigned, &Value::Int(-1)));
410        // i64::MAX can be represented as u64, so should match
411        assert!(apply_equal(&Value::Uint(i64::MAX as u64), &max_signed));
412
413        // Test with empty collections
414        let empty_bytes = Value::Bytes(vec![]);
415        let empty_string = Value::String(String::new());
416
417        assert!(apply_equal(&empty_bytes, &empty_bytes));
418        assert!(apply_equal(&empty_string, &empty_string));
419        assert!(!apply_equal(&empty_bytes, &empty_string));
420    }
421
422    // Tests for apply_not_equal function
423    #[test]
424    fn test_apply_not_equal_uint_same_value() {
425        let left = Value::Uint(42);
426        let right = Value::Uint(42);
427        assert!(!apply_not_equal(&left, &right));
428    }
429
430    #[test]
431    fn test_apply_not_equal_uint_different_value() {
432        let left = Value::Uint(42);
433        let right = Value::Uint(24);
434        assert!(apply_not_equal(&left, &right));
435    }
436
437    #[test]
438    fn test_apply_not_equal_uint_zero() {
439        let left = Value::Uint(0);
440        let right = Value::Uint(0);
441        assert!(!apply_not_equal(&left, &right));
442    }
443
444    #[test]
445    fn test_apply_not_equal_uint_max_value() {
446        let left = Value::Uint(u64::MAX);
447        let right = Value::Uint(u64::MAX);
448        assert!(!apply_not_equal(&left, &right));
449
450        let left = Value::Uint(u64::MAX);
451        let right = Value::Uint(0);
452        assert!(apply_not_equal(&left, &right));
453    }
454
455    #[test]
456    fn test_apply_not_equal_int_same_value() {
457        let left = Value::Int(42);
458        let right = Value::Int(42);
459        assert!(!apply_not_equal(&left, &right));
460    }
461
462    #[test]
463    fn test_apply_not_equal_int_different_value() {
464        let left = Value::Int(42);
465        let right = Value::Int(-42);
466        assert!(apply_not_equal(&left, &right));
467    }
468
469    #[test]
470    fn test_apply_not_equal_int_negative() {
471        let left = Value::Int(-100);
472        let right = Value::Int(-100);
473        assert!(!apply_not_equal(&left, &right));
474
475        let left = Value::Int(-100);
476        let right = Value::Int(100);
477        assert!(apply_not_equal(&left, &right));
478    }
479
480    #[test]
481    fn test_apply_not_equal_int_zero() {
482        let left = Value::Int(0);
483        let right = Value::Int(0);
484        assert!(!apply_not_equal(&left, &right));
485    }
486
487    #[test]
488    fn test_apply_not_equal_int_extreme_values() {
489        let left = Value::Int(i64::MAX);
490        let right = Value::Int(i64::MAX);
491        assert!(!apply_not_equal(&left, &right));
492
493        let left = Value::Int(i64::MIN);
494        let right = Value::Int(i64::MIN);
495        assert!(!apply_not_equal(&left, &right));
496
497        let left = Value::Int(i64::MAX);
498        let right = Value::Int(i64::MIN);
499        assert!(apply_not_equal(&left, &right));
500    }
501
502    #[test]
503    fn test_apply_not_equal_bytes_same_value() {
504        let left = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
505        let right = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
506        assert!(!apply_not_equal(&left, &right));
507    }
508
509    #[test]
510    fn test_apply_not_equal_bytes_different_value() {
511        let left = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
512        let right = Value::Bytes(vec![0x50, 0x4b, 0x03, 0x04]);
513        assert!(apply_not_equal(&left, &right));
514    }
515
516    #[test]
517    fn test_apply_not_equal_bytes_empty() {
518        let left = Value::Bytes(vec![]);
519        let right = Value::Bytes(vec![]);
520        assert!(!apply_not_equal(&left, &right));
521    }
522
523    #[test]
524    fn test_apply_not_equal_bytes_different_length() {
525        let left = Value::Bytes(vec![0x7f, 0x45]);
526        let right = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
527        assert!(apply_not_equal(&left, &right));
528    }
529
530    #[test]
531    fn test_apply_not_equal_bytes_single_byte() {
532        let left = Value::Bytes(vec![0x7f]);
533        let right = Value::Bytes(vec![0x7f]);
534        assert!(!apply_not_equal(&left, &right));
535
536        let left = Value::Bytes(vec![0x7f]);
537        let right = Value::Bytes(vec![0x45]);
538        assert!(apply_not_equal(&left, &right));
539    }
540
541    #[test]
542    fn test_apply_not_equal_string_same_value() {
543        let left = Value::String("hello".to_string());
544        let right = Value::String("hello".to_string());
545        assert!(!apply_not_equal(&left, &right));
546    }
547
548    #[test]
549    fn test_apply_not_equal_string_different_value() {
550        let left = Value::String("hello".to_string());
551        let right = Value::String("world".to_string());
552        assert!(apply_not_equal(&left, &right));
553    }
554
555    #[test]
556    fn test_apply_not_equal_string_empty() {
557        let left = Value::String(String::new());
558        let right = Value::String(String::new());
559        assert!(!apply_not_equal(&left, &right));
560    }
561
562    #[test]
563    fn test_apply_not_equal_string_case_sensitive() {
564        let left = Value::String("Hello".to_string());
565        let right = Value::String("hello".to_string());
566        assert!(apply_not_equal(&left, &right));
567    }
568
569    #[test]
570    fn test_apply_not_equal_string_unicode() {
571        let left = Value::String("\u{1f980} Rust".to_string());
572        let right = Value::String("\u{1f980} Rust".to_string());
573        assert!(!apply_not_equal(&left, &right));
574
575        let left = Value::String("\u{1f980} Rust".to_string());
576        let right = Value::String("\u{1f40d} Python".to_string());
577        assert!(apply_not_equal(&left, &right));
578    }
579
580    #[test]
581    fn test_apply_not_equal_string_whitespace() {
582        let left = Value::String("hello world".to_string());
583        let right = Value::String("hello world".to_string());
584        assert!(!apply_not_equal(&left, &right));
585
586        let left = Value::String("hello world".to_string());
587        let right = Value::String("hello  world".to_string()); // Extra space
588        assert!(apply_not_equal(&left, &right));
589    }
590
591    // Cross-type comparison tests for not_equal (should all return true)
592    #[test]
593    fn test_apply_not_equal_uint_vs_int() {
594        // Same numeric value across types should be equal (not not-equal)
595        let left = Value::Uint(42);
596        let right = Value::Int(42);
597        assert!(!apply_not_equal(&left, &right));
598
599        let left = Value::Uint(0);
600        let right = Value::Int(0);
601        assert!(!apply_not_equal(&left, &right));
602
603        // Different numeric values should be not-equal
604        let left = Value::Uint(42);
605        let right = Value::Int(-42);
606        assert!(apply_not_equal(&left, &right));
607    }
608
609    #[test]
610    fn test_apply_not_equal_uint_vs_bytes() {
611        let left = Value::Uint(42);
612        let right = Value::Bytes(vec![42]);
613        assert!(apply_not_equal(&left, &right));
614    }
615
616    #[test]
617    fn test_apply_not_equal_uint_vs_string() {
618        let left = Value::Uint(42);
619        let right = Value::String("42".to_string());
620        assert!(apply_not_equal(&left, &right));
621    }
622
623    #[test]
624    fn test_apply_not_equal_int_vs_bytes() {
625        let left = Value::Int(-42);
626        let right = Value::Bytes(vec![214]); // -42 as u8
627        assert!(apply_not_equal(&left, &right));
628    }
629
630    #[test]
631    fn test_apply_not_equal_int_vs_string() {
632        let left = Value::Int(-42);
633        let right = Value::String("-42".to_string());
634        assert!(apply_not_equal(&left, &right));
635    }
636
637    #[test]
638    fn test_apply_not_equal_bytes_vs_string() {
639        let left = Value::Bytes(vec![104, 101, 108, 108, 111]); // "hello" as bytes
640        let right = Value::String("hello".to_string());
641        assert!(apply_not_equal(&left, &right));
642    }
643
644    #[test]
645    fn test_apply_not_equal_all_cross_type_combinations() {
646        let values = [
647            Value::Uint(42),
648            Value::Int(42),
649            Value::Bytes(vec![42]),
650            Value::String("42".to_string()),
651        ];
652
653        // Test cross-type comparisons for not_equal
654        for (i, left) in values.iter().enumerate() {
655            for (j, right) in values.iter().enumerate() {
656                if i != j {
657                    let result = apply_not_equal(left, right);
658                    // Uint(42) and Int(42) should be equal, so not_equal is false
659                    if (i <= 1) && (j <= 1) {
660                        assert!(
661                            !result,
662                            "Integer cross-type not_equal should be false: {left:?} vs {right:?}"
663                        );
664                    } else {
665                        assert!(
666                            result,
667                            "Non-integer cross-type not_equal should be true: {left:?} vs {right:?}"
668                        );
669                    }
670                }
671            }
672        }
673    }
674
675    #[test]
676    fn test_apply_not_equal_consistency_with_equal() {
677        let test_cases = vec![
678            (Value::Uint(42), Value::Uint(42)),
679            (Value::Uint(42), Value::Uint(24)),
680            (Value::Int(-100), Value::Int(-100)),
681            (Value::Int(-100), Value::Int(100)),
682            (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![1, 2, 3])),
683            (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![3, 2, 1])),
684            (
685                Value::String("test".to_string()),
686                Value::String("test".to_string()),
687            ),
688            (
689                Value::String("test".to_string()),
690                Value::String("different".to_string()),
691            ),
692            // Cross-type cases
693            (Value::Uint(42), Value::Int(42)),
694            (Value::Uint(42), Value::String("42".to_string())),
695            (Value::Bytes(vec![42]), Value::Uint(42)),
696        ];
697
698        // Test that apply_not_equal is always the negation of apply_equal
699        for (left, right) in test_cases {
700            let equal_result = apply_equal(&left, &right);
701            let not_equal_result = apply_not_equal(&left, &right);
702            assert_eq!(
703                equal_result, !not_equal_result,
704                "apply_not_equal should be negation of apply_equal: {left:?} vs {right:?}"
705            );
706        }
707    }
708
709    #[test]
710    fn test_apply_not_equal_edge_cases() {
711        // Test with maximum values
712        let max_unsigned = Value::Uint(u64::MAX);
713        let max_signed = Value::Int(i64::MAX);
714        let min_int = Value::Int(i64::MIN);
715
716        assert!(!apply_not_equal(&max_unsigned, &max_unsigned));
717        assert!(!apply_not_equal(&max_signed, &max_signed));
718        assert!(!apply_not_equal(&min_int, &min_int));
719
720        // Test with empty collections
721        let empty_bytes = Value::Bytes(vec![]);
722        let empty_string = Value::String(String::new());
723
724        assert!(!apply_not_equal(&empty_bytes, &empty_bytes));
725        assert!(!apply_not_equal(&empty_string, &empty_string));
726        assert!(apply_not_equal(&empty_bytes, &empty_string));
727    }
728
729    #[test]
730    fn test_apply_not_equal_various_value_combinations() {
731        // Test various combinations to ensure comprehensive coverage
732        let test_cases = vec![
733            // Uint variations
734            (Value::Uint(0), Value::Uint(1), true),
735            (Value::Uint(100), Value::Uint(100), false),
736            (Value::Uint(u64::MAX), Value::Uint(u64::MAX - 1), true),
737            // Int variations
738            (Value::Int(0), Value::Int(-1), true),
739            (Value::Int(-50), Value::Int(-50), false),
740            (Value::Int(i64::MIN), Value::Int(i64::MAX), true),
741            // Bytes variations
742            (Value::Bytes(vec![0]), Value::Bytes(vec![1]), true),
743            (
744                Value::Bytes(vec![255, 254]),
745                Value::Bytes(vec![255, 254]),
746                false,
747            ),
748            (Value::Bytes(vec![]), Value::Bytes(vec![0]), true),
749            // String variations
750            (
751                Value::String("a".to_string()),
752                Value::String("b".to_string()),
753                true,
754            ),
755            (
756                Value::String("same".to_string()),
757                Value::String("same".to_string()),
758                false,
759            ),
760            (
761                Value::String(String::new()),
762                Value::String("non-empty".to_string()),
763                true,
764            ),
765        ];
766
767        for (left, right, expected) in test_cases {
768            assert_eq!(
769                apply_not_equal(&left, &right),
770                expected,
771                "apply_not_equal({left:?}, {right:?}) should be {expected}"
772            );
773        }
774    }
775}