55
66use vortex_mask:: Mask ;
77
8- use crate :: { StructVectorMut , VectorOps } ;
8+ use crate :: { StructVectorMut , Vector , VectorMutOps , VectorOps } ;
99
1010/// An immutable vector of boolean values.
1111///
@@ -15,15 +15,35 @@ use crate::{StructVectorMut, VectorOps};
1515/// See the documentation for [`StructVectorMut`] for more information.
1616#[ derive( Debug , Clone ) ]
1717pub struct StructVector {
18+ /// The fields of the `StructVector`, each stored column-wise as a [`Vector`].
19+ pub ( super ) fields : Box < [ Vector ] > ,
20+
21+ /// The length of the vector (which is the same as all field vectors).
22+ ///
23+ /// This is stored here as a convenience.
24+ pub ( super ) len : usize ,
25+
26+ /// The capacity of the vector (which is the same as all field vectors).
27+ ///
28+ /// This is stored here as a convenience for converting to/from a [`StructVectorMut`].
29+ pub ( super ) capacity : usize ,
30+
1831 /// The validity mask (where `true` represents an element is **not** null).
1932 pub ( super ) validity : Mask ,
2033}
2134
35+ impl StructVector {
36+ /// Returns the fields of the `StructVector`, each stored column-wise as a [`Vector`].
37+ pub fn fields ( & self ) -> & [ Vector ] {
38+ self . fields . as_ref ( )
39+ }
40+ }
41+
2242impl VectorOps for StructVector {
2343 type Mutable = StructVectorMut ;
2444
2545 fn len ( & self ) -> usize {
26- todo ! ( )
46+ self . len
2747 }
2848
2949 fn validity ( & self ) -> & Mask {
@@ -34,6 +54,262 @@ impl VectorOps for StructVector {
3454 where
3555 Self : Sized ,
3656 {
37- todo ! ( )
57+ let validity = match self . validity . try_into_mut ( ) {
58+ Ok ( validity) => validity,
59+ Err ( validity) => {
60+ return Err ( StructVector { validity, ..self } ) ;
61+ }
62+ } ;
63+
64+ // Convert all of the remaining fields to mutable, if possible.
65+ let mut mutable_fields = Vec :: with_capacity ( self . fields . len ( ) ) ;
66+ let mut fields_iter = self . fields . into_iter ( ) ;
67+
68+ while let Some ( field) = fields_iter. next ( ) {
69+ match field. try_into_mut ( ) {
70+ Ok ( mutable_field) => {
71+ // We were able to take ownership of the field vector, so add it and keep going.
72+ mutable_fields. push ( mutable_field) ;
73+ }
74+ Err ( immutable_field) => {
75+ // We were unable to take ownership, so we must re-freeze all of the fields
76+ // vectors we took ownership over and reconstruct the original `StructVector`.
77+
78+ let mut all_fields: Vec < Vector > = mutable_fields
79+ . into_iter ( )
80+ . map ( |mut_field| mut_field. freeze ( ) )
81+ . collect ( ) ;
82+
83+ all_fields. push ( immutable_field) ;
84+ all_fields. extend ( fields_iter) ;
85+
86+ return Err ( StructVector {
87+ fields : all_fields. into_boxed_slice ( ) ,
88+ len : self . len ,
89+ capacity : self . capacity ,
90+ validity : validity. freeze ( ) ,
91+ } ) ;
92+ }
93+ }
94+ }
95+
96+ Ok ( StructVectorMut {
97+ fields : mutable_fields,
98+ len : self . len ,
99+ capacity : self . capacity ,
100+ validity,
101+ } )
102+ }
103+ }
104+
105+ #[ cfg( test) ]
106+ mod tests {
107+ use vortex_mask:: Mask ;
108+
109+ use super :: * ;
110+ use crate :: { BoolVectorMut , NullVector , PVectorMut , VectorMut } ;
111+
112+ // TODO(connor): Make sure to test actual logic instead of just lengths and capacity.
113+
114+ /// Helper function to create a `StructVector` with the given fields.
115+ fn create_struct_vector ( fields : Vec < Vector > , len : usize , capacity : usize ) -> StructVector {
116+ StructVector {
117+ fields : fields. into_boxed_slice ( ) ,
118+ len,
119+ capacity,
120+ validity : Mask :: AllTrue ( len) ,
121+ }
122+ }
123+
124+ #[ test]
125+ fn test_try_into_mut_success ( ) {
126+ // Create a `StructVector` with 3 different field types (null, bool, primitive).
127+ let null_field: Vector = NullVector :: new ( 5 ) . into ( ) ;
128+ let bool_field: Vector = BoolVectorMut :: from_iter ( [ true , false , true , false , true ] )
129+ . freeze ( )
130+ . into ( ) ;
131+ let prim_field: Vector = PVectorMut :: < i32 > :: from_iter ( [ 10 , 20 , 30 , 40 , 50 ] )
132+ . freeze ( )
133+ . into ( ) ;
134+
135+ let struct_vec = create_struct_vector ( vec ! [ null_field, bool_field, prim_field] , 5 , 5 ) ;
136+
137+ // Attempt to convert to mutable.
138+ let result = struct_vec. try_into_mut ( ) ;
139+
140+ // Should succeed since all fields have unique ownership.
141+ assert ! ( result. is_ok( ) ) ;
142+
143+ let mut_struct = result. unwrap ( ) ;
144+
145+ // Verify the mutable struct has correct length and capacity.
146+ assert_eq ! ( mut_struct. len( ) , 5 ) ;
147+ assert_eq ! ( mut_struct. capacity( ) , 5 ) ;
148+
149+ // Verify that we have 3 fields.
150+ assert_eq ! ( mut_struct. fields. len( ) , 3 ) ;
151+
152+ // Verify each field has the correct type and length.
153+ assert ! ( matches!( mut_struct. fields[ 0 ] , VectorMut :: Null ( _) ) ) ;
154+ assert_eq ! ( mut_struct. fields[ 0 ] . len( ) , 5 ) ;
155+
156+ assert ! ( matches!( mut_struct. fields[ 1 ] , VectorMut :: Bool ( _) ) ) ;
157+ assert_eq ! ( mut_struct. fields[ 1 ] . len( ) , 5 ) ;
158+ assert ! ( mut_struct. fields[ 1 ] . capacity( ) >= 5 ) ;
159+
160+ assert ! ( matches!( mut_struct. fields[ 2 ] , VectorMut :: Primitive ( _) ) ) ;
161+ assert_eq ! ( mut_struct. fields[ 2 ] . len( ) , 5 ) ;
162+ assert ! ( mut_struct. fields[ 2 ] . capacity( ) >= 5 ) ;
163+ }
164+
165+ #[ test]
166+ fn test_try_into_mut_fails_first_field ( ) {
167+ // Create a bool field with shared ownership (cloned to have Arc count > 1).
168+ let bool_field: Vector = BoolVectorMut :: from_iter ( [ true , false , true ] )
169+ . freeze ( )
170+ . into ( ) ;
171+ let bool_field_clone = bool_field. clone ( ) ;
172+
173+ let null_field: Vector = NullVector :: new ( 3 ) . into ( ) ;
174+ let prim_field: Vector = PVectorMut :: < i32 > :: from_iter ( [ 1 , 2 , 3 ] ) . freeze ( ) . into ( ) ;
175+
176+ // Create a struct with the cloned bool field as the first field.
177+ let struct_vec = create_struct_vector ( vec ! [ bool_field_clone, null_field, prim_field] , 3 , 3 ) ;
178+
179+ // Attempt to convert to mutable.
180+ let result = struct_vec. try_into_mut ( ) ;
181+
182+ // Should fail since the first field has shared ownership.
183+ assert ! ( result. is_err( ) ) ;
184+
185+ // Keep the original alive to ensure shared ownership is maintained.
186+ drop ( bool_field) ;
187+
188+ let recovered_struct = result. unwrap_err ( ) ;
189+
190+ // Verify the recovered struct has all 3 fields.
191+ assert_eq ! ( recovered_struct. fields. len( ) , 3 ) ;
192+ assert_eq ! ( recovered_struct. len( ) , 3 ) ;
193+ assert_eq ! ( recovered_struct. capacity, 3 ) ;
194+
195+ // Verify field types are preserved.
196+ assert ! ( matches!( recovered_struct. fields[ 0 ] , Vector :: Bool ( _) ) ) ;
197+ assert ! ( matches!( recovered_struct. fields[ 1 ] , Vector :: Null ( _) ) ) ;
198+ assert ! ( matches!( recovered_struct. fields[ 2 ] , Vector :: Primitive ( _) ) ) ;
199+ }
200+
201+ #[ test]
202+ fn test_try_into_mut_fails_middle_field ( ) {
203+ // Create a primitive field with shared ownership (cloned).
204+ let prim_field: Vector = PVectorMut :: < i32 > :: from_iter ( [ 100 , 200 , 300 , 400 ] )
205+ . freeze ( )
206+ . into ( ) ;
207+ let prim_field_clone = prim_field. clone ( ) ;
208+
209+ let bool_field: Vector = BoolVectorMut :: from_iter ( [ true , false , true , false ] )
210+ . freeze ( )
211+ . into ( ) ;
212+ let null_field: Vector = NullVector :: new ( 4 ) . into ( ) ;
213+
214+ // Create a struct with the cloned primitive field as the middle field.
215+ let struct_vec = create_struct_vector ( vec ! [ bool_field, prim_field_clone, null_field] , 4 , 4 ) ;
216+
217+ // Attempt to convert to mutable.
218+ let result = struct_vec. try_into_mut ( ) ;
219+
220+ // Should fail since the middle field has shared ownership.
221+ assert ! ( result. is_err( ) ) ;
222+
223+ // Keep the original alive to ensure shared ownership is maintained.
224+ drop ( prim_field) ;
225+
226+ let recovered_struct = result. unwrap_err ( ) ;
227+
228+ // Verify all 3 fields are present in the recovered struct.
229+ assert_eq ! ( recovered_struct. fields. len( ) , 3 ) ;
230+ assert_eq ! ( recovered_struct. len( ) , 4 ) ;
231+ assert_eq ! ( recovered_struct. capacity, 4 ) ;
232+
233+ // Verify field types and order are preserved.
234+ // The first field was converted to mutable then frozen back, so it should still be bool.
235+ assert ! ( matches!( recovered_struct. fields[ 0 ] , Vector :: Bool ( _) ) ) ;
236+ assert ! ( matches!( recovered_struct. fields[ 1 ] , Vector :: Primitive ( _) ) ) ;
237+ assert ! ( matches!( recovered_struct. fields[ 2 ] , Vector :: Null ( _) ) ) ;
238+ }
239+
240+ #[ test]
241+ fn test_try_into_mut_fails_last_field ( ) {
242+ // Create a null field with "shared ownership" (though NullVector always succeeds, we test
243+ // the pattern by cloning a bool vector).
244+ let bool_field_last: Vector = BoolVectorMut :: from_iter ( [ true , true ] ) . freeze ( ) . into ( ) ;
245+ let bool_field_last_clone = bool_field_last. clone ( ) ;
246+
247+ let null_field: Vector = NullVector :: new ( 2 ) . into ( ) ;
248+ let prim_field: Vector = PVectorMut :: < u64 > :: from_iter ( [ 1000 , 2000 ] ) . freeze ( ) . into ( ) ;
249+
250+ // Create a struct with the cloned bool field as the last field.
251+ let struct_vec =
252+ create_struct_vector ( vec ! [ null_field, prim_field, bool_field_last_clone] , 2 , 2 ) ;
253+
254+ // Attempt to convert to mutable.
255+ let result = struct_vec. try_into_mut ( ) ;
256+
257+ // Should fail since the last field has shared ownership.
258+ assert ! ( result. is_err( ) ) ;
259+
260+ // Keep the original alive to ensure shared ownership is maintained.
261+ drop ( bool_field_last) ;
262+
263+ let recovered_struct = result. unwrap_err ( ) ;
264+
265+ // Verify all 3 fields are present.
266+ assert_eq ! ( recovered_struct. fields. len( ) , 3 ) ;
267+ assert_eq ! ( recovered_struct. len( ) , 2 ) ;
268+ assert_eq ! ( recovered_struct. capacity, 2 ) ;
269+
270+ // Verify field types are preserved.
271+ // The first two fields were converted to mutable then frozen back.
272+ assert ! ( matches!( recovered_struct. fields[ 0 ] , Vector :: Null ( _) ) ) ;
273+ assert ! ( matches!( recovered_struct. fields[ 1 ] , Vector :: Primitive ( _) ) ) ;
274+ assert ! ( matches!( recovered_struct. fields[ 2 ] , Vector :: Bool ( _) ) ) ;
275+ }
276+
277+ #[ test]
278+ fn test_try_into_mut_nested_struct ( ) {
279+ // Create a nested struct: a `StructVector` containing other `StructVector`s as fields.
280+ let inner_struct1: Vector = create_struct_vector (
281+ vec ! [
282+ NullVector :: new( 3 ) . into( ) ,
283+ BoolVectorMut :: from_iter( [ true , false , true ] )
284+ . freeze( )
285+ . into( ) ,
286+ ] ,
287+ 3 ,
288+ 3 ,
289+ )
290+ . into ( ) ;
291+
292+ let inner_struct2: Vector = create_struct_vector (
293+ vec ! [ PVectorMut :: <i32 >:: from_iter( [ 1 , 2 , 3 ] ) . freeze( ) . into( ) ] ,
294+ 3 ,
295+ 3 ,
296+ )
297+ . into ( ) ;
298+
299+ let outer_struct = create_struct_vector ( vec ! [ inner_struct1, inner_struct2] , 3 , 3 ) ;
300+
301+ // Attempt to convert to mutable.
302+ let result = outer_struct. try_into_mut ( ) ;
303+
304+ // Should succeed once `StructVectorMut` is fully implemented.
305+ assert ! ( result. is_ok( ) ) ;
306+
307+ let mut_struct = result. unwrap ( ) ;
308+ assert_eq ! ( mut_struct. len( ) , 3 ) ;
309+ assert_eq ! ( mut_struct. fields. len( ) , 2 ) ;
310+
311+ // Verify nested structs are converted correctly.
312+ assert ! ( matches!( mut_struct. fields[ 0 ] , VectorMut :: Struct ( _) ) ) ;
313+ assert ! ( matches!( mut_struct. fields[ 1 ] , VectorMut :: Struct ( _) ) ) ;
38314 }
39315}
0 commit comments