@@ -422,6 +422,11 @@ impl VariantArray {
422422 pub fn is_valid ( & self , index : usize ) -> bool {
423423 !self . is_null ( index)
424424 }
425+
426+ /// Returns an iterator over the values in this array
427+ pub fn iter ( & self ) -> VariantArrayIter < ' _ > {
428+ VariantArrayIter :: new ( self )
429+ }
425430}
426431
427432impl From < VariantArray > for StructArray {
@@ -436,6 +441,99 @@ impl From<VariantArray> for ArrayRef {
436441 }
437442}
438443
444+ /// An iterator over [`VariantArray`]
445+ ///
446+ /// This iterator returns `Option<Option<Variant<'a, 'a>>>` where:
447+ /// - `None` indicates the end of iteration
448+ /// - `Some(None)` indicates a null value at this position
449+ /// - `Some(Some(variant))` indicates a valid variant value
450+ ///
451+ /// # Example
452+ ///
453+ /// ```
454+ /// # use parquet_variant::Variant;
455+ /// # use parquet_variant_compute::VariantArrayBuilder;
456+ /// let mut builder = VariantArrayBuilder::new(10);
457+ /// builder.append_variant(Variant::from(42));
458+ /// builder.append_null();
459+ /// builder.append_variant(Variant::from("hello"));
460+ /// let array = builder.build();
461+ ///
462+ /// let values = array.iter().collect::<Vec<_>>();
463+ /// assert_eq!(values.len(), 3);
464+ /// assert_eq!(values[0], Some(Variant::from(42)));
465+ /// assert_eq!(values[1], None);
466+ /// assert_eq!(values[2], Some(Variant::from("hello")));
467+ /// ```
468+ #[ derive( Debug ) ]
469+ pub struct VariantArrayIter < ' a > {
470+ array : & ' a VariantArray ,
471+ head_i : usize ,
472+ tail_i : usize ,
473+ }
474+
475+ impl < ' a > VariantArrayIter < ' a > {
476+ /// Creates a new iterator over the given [`VariantArray`]
477+ pub fn new ( array : & ' a VariantArray ) -> Self {
478+ Self {
479+ array,
480+ head_i : 0 ,
481+ tail_i : array. len ( ) ,
482+ }
483+ }
484+
485+ /// Helper method to check if the value at the given index is null
486+ #[ inline]
487+ fn is_null ( & self , idx : usize ) -> bool {
488+ self . array . is_null ( idx)
489+ }
490+ }
491+
492+ impl < ' a > Iterator for VariantArrayIter < ' a > {
493+ type Item = Option < Variant < ' a , ' a > > ;
494+
495+ #[ inline]
496+ fn next ( & mut self ) -> Option < Self :: Item > {
497+ if self . head_i == self . tail_i {
498+ return None ;
499+ }
500+
501+ let out = if self . is_null ( self . head_i ) {
502+ Some ( None )
503+ } else {
504+ Some ( Some ( self . array . value ( self . head_i ) ) )
505+ } ;
506+
507+ self . head_i += 1 ;
508+
509+ out
510+ }
511+
512+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
513+ let remainder = self . tail_i - self . head_i ;
514+
515+ ( remainder, Some ( remainder) )
516+ }
517+ }
518+
519+ impl < ' a > DoubleEndedIterator for VariantArrayIter < ' a > {
520+ fn next_back ( & mut self ) -> Option < Self :: Item > {
521+ if self . head_i == self . tail_i {
522+ return None ;
523+ }
524+
525+ self . tail_i -= 1 ;
526+
527+ if self . is_null ( self . tail_i ) {
528+ Some ( None )
529+ } else {
530+ Some ( Some ( self . array . value ( self . tail_i ) ) )
531+ }
532+ }
533+ }
534+
535+ impl < ' a > ExactSizeIterator for VariantArrayIter < ' a > { }
536+
439537/// One shredded field of a partially or prefectly shredded variant. For example, suppose the
440538/// shredding schema for variant `v` treats it as an object with a single field `a`, where `a` is
441539/// itself a struct with the single field `b` of type INT. Then the physical layout of the column
@@ -1062,6 +1160,8 @@ fn canonicalize_and_verify_field(field: &Arc<Field>) -> Result<Cow<'_, Arc<Field
10621160
10631161#[ cfg( test) ]
10641162mod test {
1163+ use crate :: VariantArrayBuilder ;
1164+
10651165 use super :: * ;
10661166 use arrow:: array:: { BinaryViewArray , Int32Array } ;
10671167 use arrow_schema:: { Field , Fields } ;
@@ -1244,4 +1344,88 @@ mod test {
12441344 }
12451345 ) ) ;
12461346 }
1347+
1348+ #[ test]
1349+ fn test_variant_array_iterable ( ) {
1350+ let mut b = VariantArrayBuilder :: new ( 6 ) ;
1351+
1352+ b. append_null ( ) ;
1353+ b. append_variant ( Variant :: from ( 1_i8 ) ) ;
1354+ b. append_variant ( Variant :: Null ) ;
1355+ b. append_variant ( Variant :: from ( 2_i32 ) ) ;
1356+ b. append_variant ( Variant :: from ( 3_i64 ) ) ;
1357+ b. append_null ( ) ;
1358+
1359+ let v = b. build ( ) ;
1360+
1361+ let variants = v. iter ( ) . collect :: < Vec < _ > > ( ) ;
1362+
1363+ assert_eq ! (
1364+ variants,
1365+ vec![
1366+ None ,
1367+ Some ( Variant :: Int8 ( 1 ) ) ,
1368+ Some ( Variant :: Null ) ,
1369+ Some ( Variant :: Int32 ( 2 ) ) ,
1370+ Some ( Variant :: Int64 ( 3 ) ) ,
1371+ None ,
1372+ ]
1373+ ) ;
1374+ }
1375+
1376+ #[ test]
1377+ fn test_variant_array_iter_double_ended ( ) {
1378+ let mut b = VariantArrayBuilder :: new ( 5 ) ;
1379+
1380+ b. append_variant ( Variant :: from ( 0_i32 ) ) ;
1381+ b. append_null ( ) ;
1382+ b. append_variant ( Variant :: from ( 2_i32 ) ) ;
1383+ b. append_null ( ) ;
1384+ b. append_variant ( Variant :: from ( 4_i32 ) ) ;
1385+
1386+ let array = b. build ( ) ;
1387+ let mut iter = array. iter ( ) ;
1388+
1389+ assert_eq ! ( iter. next( ) , Some ( Some ( Variant :: from( 0_i32 ) ) ) ) ;
1390+ assert_eq ! ( iter. next( ) , Some ( None ) ) ;
1391+
1392+ assert_eq ! ( iter. next_back( ) , Some ( Some ( Variant :: from( 4_i32 ) ) ) ) ;
1393+ assert_eq ! ( iter. next_back( ) , Some ( None ) ) ;
1394+ assert_eq ! ( iter. next_back( ) , Some ( Some ( Variant :: from( 2_i32 ) ) ) ) ;
1395+
1396+ assert_eq ! ( iter. next_back( ) , None ) ;
1397+ assert_eq ! ( iter. next( ) , None ) ;
1398+ }
1399+
1400+ #[ test]
1401+ fn test_variant_array_iter_reverse ( ) {
1402+ let mut b = VariantArrayBuilder :: new ( 5 ) ;
1403+
1404+ b. append_variant ( Variant :: from ( "a" ) ) ;
1405+ b. append_null ( ) ;
1406+ b. append_variant ( Variant :: from ( "aaa" ) ) ;
1407+ b. append_null ( ) ;
1408+ b. append_variant ( Variant :: from ( "aaaaa" ) ) ;
1409+
1410+ let array = b. build ( ) ;
1411+
1412+ let result: Vec < _ > = array. iter ( ) . rev ( ) . collect ( ) ;
1413+ assert_eq ! (
1414+ result,
1415+ vec![
1416+ Some ( Variant :: from( "aaaaa" ) ) ,
1417+ None ,
1418+ Some ( Variant :: from( "aaa" ) ) ,
1419+ None ,
1420+ Some ( Variant :: from( "a" ) ) ,
1421+ ]
1422+ ) ;
1423+ }
1424+
1425+ #[ test]
1426+ fn test_variant_array_iter_empty ( ) {
1427+ let v = VariantArrayBuilder :: new ( 0 ) . build ( ) ;
1428+ let mut i = v. iter ( ) ;
1429+ assert ! ( i. next( ) . is_none( ) ) ;
1430+ }
12471431}
0 commit comments