@@ -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,101 @@ 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+ /// This iterator follows similar conventions to [`ArrayIter`] from arrow-array.
452+ ///
453+ /// # Example
454+ ///
455+ /// ```
456+ /// # use parquet_variant::Variant;
457+ /// # use parquet_variant_compute::VariantArrayBuilder;
458+ /// let mut builder = VariantArrayBuilder::new(10);
459+ /// builder.append_variant(Variant::from(42));
460+ /// builder.append_null();
461+ /// builder.append_variant(Variant::from("hello"));
462+ /// let array = builder.build();
463+ ///
464+ /// let values = array.iter().collect::<Vec<_>>();
465+ /// assert_eq!(values.len(), 3);
466+ /// assert_eq!(values[0], Some(Variant::from(42)));
467+ /// assert_eq!(values[1], None);
468+ /// assert_eq!(values[2], Some(Variant::from("hello")));
469+ /// ```
470+ #[ derive( Debug ) ]
471+ pub struct VariantArrayIter < ' a > {
472+ array : & ' a VariantArray ,
473+ head_i : usize ,
474+ tail_i : usize ,
475+ }
476+
477+ impl < ' a > VariantArrayIter < ' a > {
478+ /// Creates a new iterator over the given [`VariantArray`]
479+ pub fn new ( array : & ' a VariantArray ) -> Self {
480+ Self {
481+ array,
482+ head_i : 0 ,
483+ tail_i : array. len ( ) ,
484+ }
485+ }
486+
487+ /// Helper method to check if the value at the given index is null
488+ #[ inline]
489+ fn is_null ( & self , idx : usize ) -> bool {
490+ self . array . is_null ( idx)
491+ }
492+ }
493+
494+ impl < ' a > Iterator for VariantArrayIter < ' a > {
495+ type Item = Option < Variant < ' a , ' a > > ;
496+
497+ #[ inline]
498+ fn next ( & mut self ) -> Option < Self :: Item > {
499+ if self . head_i == self . tail_i {
500+ return None ;
501+ }
502+
503+ let out = if self . is_null ( self . head_i ) {
504+ Some ( None )
505+ } else {
506+ Some ( Some ( self . array . value ( self . head_i ) ) )
507+ } ;
508+
509+ self . head_i += 1 ;
510+
511+ return out;
512+ }
513+
514+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
515+ let remainder = self . tail_i - self . head_i ;
516+
517+ ( remainder, Some ( remainder) )
518+ }
519+ }
520+
521+ impl < ' a > DoubleEndedIterator for VariantArrayIter < ' a > {
522+ fn next_back ( & mut self ) -> Option < Self :: Item > {
523+ if self . head_i == self . tail_i {
524+ return None ;
525+ }
526+
527+ self . tail_i -= 1 ;
528+
529+ if self . is_null ( self . tail_i ) {
530+ Some ( None )
531+ } else {
532+ Some ( Some ( self . array . value ( self . tail_i ) ) )
533+ }
534+ }
535+ }
536+
537+ impl < ' a > ExactSizeIterator for VariantArrayIter < ' a > { }
538+
439539/// One shredded field of a partially or prefectly shredded variant. For example, suppose the
440540/// shredding schema for variant `v` treats it as an object with a single field `a`, where `a` is
441541/// itself a struct with the single field `b` of type INT. Then the physical layout of the column
@@ -1062,6 +1162,8 @@ fn canonicalize_and_verify_field(field: &Arc<Field>) -> Result<Cow<'_, Arc<Field
10621162
10631163#[ cfg( test) ]
10641164mod test {
1165+ use crate :: VariantArrayBuilder ;
1166+
10651167 use super :: * ;
10661168 use arrow:: array:: { BinaryViewArray , Int32Array } ;
10671169 use arrow_schema:: { Field , Fields } ;
@@ -1244,4 +1346,81 @@ mod test {
12441346 }
12451347 ) ) ;
12461348 }
1349+
1350+ #[ test]
1351+ fn test_variant_array_iterable ( ) {
1352+ let mut b = VariantArrayBuilder :: new ( 6 ) ;
1353+
1354+ b. append_null ( ) ;
1355+ b. append_variant ( Variant :: from ( 1_i8 ) ) ;
1356+ b. append_variant ( Variant :: Null ) ;
1357+ b. append_variant ( Variant :: from ( 2_i32 ) ) ;
1358+ b. append_variant ( Variant :: from ( 3_i64 ) ) ;
1359+ b. append_null ( ) ;
1360+
1361+ let v = b. build ( ) ;
1362+
1363+ let variants = v. iter ( ) . collect :: < Vec < _ > > ( ) ;
1364+
1365+ assert_eq ! (
1366+ variants,
1367+ vec![
1368+ None ,
1369+ Some ( Variant :: Int8 ( 1 ) ) ,
1370+ Some ( Variant :: Null ) ,
1371+ Some ( Variant :: Int32 ( 2 ) ) ,
1372+ Some ( Variant :: Int64 ( 3 ) ) ,
1373+ None ,
1374+ ]
1375+ ) ;
1376+ }
1377+
1378+ #[ test]
1379+ fn test_variant_array_iter_double_ended ( ) {
1380+ let mut b = VariantArrayBuilder :: new ( 5 ) ;
1381+
1382+ b. append_variant ( Variant :: from ( 0_i32 ) ) ;
1383+ b. append_null ( ) ;
1384+ b. append_variant ( Variant :: from ( 2_i32 ) ) ;
1385+ b. append_null ( ) ;
1386+ b. append_variant ( Variant :: from ( 4_i32 ) ) ;
1387+
1388+ let array = b. build ( ) ;
1389+ let mut iter = array. iter ( ) ;
1390+
1391+ assert_eq ! ( iter. next( ) , Some ( Some ( Variant :: from( 0_i32 ) ) ) ) ;
1392+ assert_eq ! ( iter. next( ) , Some ( None ) ) ;
1393+
1394+ assert_eq ! ( iter. next_back( ) , Some ( Some ( Variant :: from( 4_i32 ) ) ) ) ;
1395+ assert_eq ! ( iter. next_back( ) , Some ( None ) ) ;
1396+ assert_eq ! ( iter. next_back( ) , Some ( Some ( Variant :: from( 2_i32 ) ) ) ) ;
1397+
1398+ assert_eq ! ( iter. next_back( ) , None ) ;
1399+ assert_eq ! ( iter. next( ) , None ) ;
1400+ }
1401+
1402+ #[ test]
1403+ fn test_variant_array_iter_reverse ( ) {
1404+ let mut b = VariantArrayBuilder :: new ( 5 ) ;
1405+
1406+ b. append_variant ( Variant :: from ( "a" ) ) ;
1407+ b. append_null ( ) ;
1408+ b. append_variant ( Variant :: from ( "aaa" ) ) ;
1409+ b. append_null ( ) ;
1410+ b. append_variant ( Variant :: from ( "aaaaa" ) ) ;
1411+
1412+ let array = b. build ( ) ;
1413+
1414+ let result: Vec < _ > = array. iter ( ) . rev ( ) . collect ( ) ;
1415+ assert_eq ! (
1416+ result,
1417+ vec![
1418+ Some ( Variant :: from( "aaaaa" ) ) ,
1419+ None ,
1420+ Some ( Variant :: from( "aaa" ) ) ,
1421+ None ,
1422+ Some ( Variant :: from( "a" ) ) ,
1423+ ]
1424+ ) ;
1425+ }
12471426}
0 commit comments