11use std:: hash:: Hash ;
22use std:: sync:: Arc ;
33
4- use vortex_error:: { VortexExpect , VortexResult , VortexUnwrap , vortex_err, vortex_panic} ;
4+ use itertools:: Itertools ;
5+ use vortex_error:: {
6+ VortexExpect , VortexResult , VortexUnwrap , vortex_bail, vortex_err, vortex_panic,
7+ } ;
58
69use crate :: flatbuffers:: ViewedDType ;
710use crate :: { DType , FieldName , FieldNames , PType } ;
@@ -283,6 +286,33 @@ impl StructFields {
283286
284287 StructFields :: from_fields ( names, dtypes)
285288 }
289+
290+ /// Merge two [`StructFields`] instances into a new one.
291+ /// Order of fields in arguments is preserved
292+ ///
293+ /// # Errors
294+ /// Returns an error if the merged struct would have duplicate field names.
295+ pub fn disjoint_merge ( & self , other : & Self ) -> VortexResult < Self > {
296+ let names = self
297+ . names
298+ . iter ( )
299+ . chain ( other. names . iter ( ) )
300+ . cloned ( )
301+ . collect :: < FieldNames > ( ) ;
302+
303+ if !names. iter ( ) . all_unique ( ) {
304+ vortex_bail ! ( "Can't merge struct fields with duplicate names" ) ;
305+ }
306+
307+ let dtypes = self
308+ . dtypes
309+ . iter ( )
310+ . chain ( other. dtypes . iter ( ) )
311+ . cloned ( )
312+ . collect :: < Vec < _ > > ( ) ;
313+
314+ Ok ( Self :: from_fields ( names, dtypes) )
315+ }
286316}
287317
288318impl < T , V > FromIterator < ( T , V ) > for StructFields
@@ -301,8 +331,10 @@ where
301331
302332#[ cfg( test) ]
303333mod test {
334+ use itertools:: Itertools ;
335+
304336 use crate :: dtype:: DType ;
305- use crate :: { Nullability , PType , StructFields } ;
337+ use crate :: { FieldNames , Nullability , PType , StructFields } ;
306338
307339 #[ test]
308340 fn nullability ( ) {
@@ -356,4 +388,28 @@ mod test {
356388 assert_eq ! ( without_a. field_by_index( 0 ) . unwrap( ) , b_type) ;
357389 assert_eq ! ( without_a. nfields( ) , 1 ) ;
358390 }
391+
392+ #[ test]
393+ fn test_merge ( ) {
394+ let child_a = DType :: Primitive ( PType :: I32 , Nullability :: NonNullable ) ;
395+ let child_b = DType :: Bool ( Nullability :: Nullable ) ;
396+ let child_c = DType :: Utf8 ( Nullability :: NonNullable ) ;
397+
398+ let sf1 = StructFields :: from_iter ( [ ( "A" , child_a. clone ( ) ) , ( "B" , child_b. clone ( ) ) ] ) ;
399+
400+ let sf2 = StructFields :: from_iter ( [ ( "C" , child_c. clone ( ) ) ] ) ;
401+
402+ let merged = StructFields :: disjoint_merge ( & sf1, & sf2) . unwrap ( ) ;
403+ assert_eq ! (
404+ merged. names( ) ,
405+ & FieldNames :: from_iter( [ "A" . into( ) , "B" . into( ) , "C" . into( ) ] )
406+ ) ;
407+ assert_eq ! (
408+ merged. fields( ) . collect_vec( ) ,
409+ vec![ child_a, child_b, child_c]
410+ ) ;
411+
412+ let err = StructFields :: disjoint_merge ( & sf1, & sf1) . err ( ) . unwrap ( ) ;
413+ assert ! ( err. to_string( ) . contains( "duplicate names" ) , ) ;
414+ }
359415}
0 commit comments