@@ -17,6 +17,7 @@ use super::ListViewScalar;
1717use super :: ListViewVectorMut ;
1818use crate :: Vector ;
1919use crate :: match_each_integer_pvector;
20+ use crate :: match_each_integer_pvector_pair;
2021use crate :: primitive:: PrimitiveVector ;
2122use crate :: vector_ops:: VectorMutOps ;
2223use crate :: vector_ops:: VectorOps ;
@@ -65,58 +66,91 @@ pub struct ListViewVector {
6566}
6667
6768impl PartialEq for ListViewVector {
68- #[ allow( clippy:: cast_possible_truncation) ]
6969 fn eq ( & self , other : & Self ) -> bool {
7070 if self . len != other. len {
7171 return false ;
7272 }
73- // Validity patterns must match
7473 if self . validity != other. validity {
7574 return false ;
7675 }
77- // Elements lengths must match
7876 if self . elements . len ( ) != other. elements . len ( ) {
7977 return false ;
8078 }
81- // Build element-level mask: for each valid list, mark elements[offset..offset+size] as valid
82- let valid_slices: Vec < ( usize , usize ) > = ( 0 ..self . len )
83- . filter ( |& i| self . validity . value ( i) )
84- . map ( |i| {
85- let offset =
86- match_each_integer_pvector ! ( & self . offsets, |v| { v. as_ref( ) [ i] as usize } ) ;
87- let size = match_each_integer_pvector ! ( & self . sizes, |v| { v. as_ref( ) [ i] as usize } ) ;
88- ( offset, offset + size)
89- } )
90- . collect ( ) ;
91- let element_mask = Mask :: from_slices ( self . elements . len ( ) , valid_slices) ;
92-
93- // Clone elements and apply the element-level mask
94- let mut self_elements = self . elements . as_ref ( ) . clone ( ) ;
95- let mut other_elements = other. elements . as_ref ( ) . clone ( ) ;
96- self_elements. mask_validity ( & element_mask) ;
97- other_elements. mask_validity ( & element_mask) ;
98-
99- // Compare masked elements
100- if self_elements != other_elements {
101- return false ;
102- }
10379
104- // Compare offsets and sizes at valid positions
105- ( 0 ..self . len ) . all ( |i| {
106- if !self . validity . value ( i) {
107- return true ;
108- }
109- let self_offset =
110- match_each_integer_pvector ! ( & self . offsets, |v| { v. as_ref( ) [ i] as usize } ) ;
111- let other_offset =
112- match_each_integer_pvector ! ( & other. offsets, |v| { v. as_ref( ) [ i] as usize } ) ;
113- let self_size =
114- match_each_integer_pvector ! ( & self . sizes, |v| { v. as_ref( ) [ i] as usize } ) ;
115- let other_size =
116- match_each_integer_pvector ! ( & other. sizes, |v| { v. as_ref( ) [ i] as usize } ) ;
117- self_offset == other_offset && self_size == other_size
80+ // Offsets and sizes must have matching types, then compare within the match
81+ match_each_integer_pvector_pair ! (
82+ ( & self . offsets, & other. offsets) ,
83+ |self_offsets, other_offsets| {
84+ match_each_integer_pvector_pair!(
85+ ( & self . sizes, & other. sizes) ,
86+ |self_sizes, other_sizes| {
87+ listview_eq_impl(
88+ self . len,
89+ & self . validity,
90+ self . elements. as_ref( ) ,
91+ other. elements. as_ref( ) ,
92+ self_offsets,
93+ other_offsets,
94+ self_sizes,
95+ other_sizes,
96+ )
97+ } ,
98+ { false } // Size types don't match
99+ )
100+ } ,
101+ { false } // Offset types don't match
102+ )
103+ }
104+ }
105+
106+ /// Helper function for ListViewVector equality comparison.
107+ #[ expect( clippy:: too_many_arguments) ]
108+ fn listview_eq_impl < O , S > (
109+ len : usize ,
110+ validity : & Mask ,
111+ self_elements : & Vector ,
112+ other_elements : & Vector ,
113+ self_offsets : & crate :: primitive:: PVector < O > ,
114+ other_offsets : & crate :: primitive:: PVector < O > ,
115+ self_sizes : & crate :: primitive:: PVector < S > ,
116+ other_sizes : & crate :: primitive:: PVector < S > ,
117+ ) -> bool
118+ where
119+ O : vortex_dtype:: NativePType + Copy ,
120+ S : vortex_dtype:: NativePType + Copy ,
121+ usize : TryFrom < O > + TryFrom < S > ,
122+ {
123+ // Build element-level mask: for each valid list, mark elements[offset..offset+size] as valid
124+ let valid_slices: Vec < ( usize , usize ) > = ( 0 ..len)
125+ . filter ( |& i| validity. value ( i) )
126+ . map ( |i| {
127+ let offset = self_offsets
128+ . get_as :: < usize > ( i)
129+ . vortex_expect ( "offset is valid and fits in usize" ) ;
130+ let size = self_sizes
131+ . get_as :: < usize > ( i)
132+ . vortex_expect ( "size is valid and fits in usize" ) ;
133+ ( offset, offset + size)
118134 } )
135+ . collect ( ) ;
136+ let element_mask = Mask :: from_slices ( self_elements. len ( ) , valid_slices) ;
137+
138+ // Clone elements and apply the element-level mask
139+ let mut self_elems = self_elements. clone ( ) ;
140+ let mut other_elems = other_elements. clone ( ) ;
141+ self_elems. mask_validity ( & element_mask) ;
142+ other_elems. mask_validity ( & element_mask) ;
143+
144+ if self_elems != other_elems {
145+ return false ;
119146 }
147+
148+ // Compare offsets and sizes at valid positions
149+ ( 0 ..len) . all ( |i| {
150+ !validity. value ( i)
151+ || ( self_offsets. get_as :: < usize > ( i) == other_offsets. get_as :: < usize > ( i)
152+ && self_sizes. get_as :: < usize > ( i) == other_sizes. get_as :: < usize > ( i) )
153+ } )
120154}
121155
122156impl ListViewVector {
0 commit comments