This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b61796582 fix: first next_back() on new RowsIter panics (#9505)
3b61796582 is described below

commit 3b6179658203dc1b1610b67c1777d5b8beb137fc
Author: Raz Luvaton <[email protected]>
AuthorDate: Wed Mar 18 16:27:12 2026 +0200

    fix: first next_back() on new RowsIter panics (#9505)
    
    # Which issue does this PR close?
    
    N/A
    
    # Rationale for this change
    
    it should not panic
    
    # What changes are included in this PR?
    
    correctly use last row in `next_back`
    
    # Are these changes tested?
    
    yes
    
    # Are there any user-facing changes?
    
    they can now use `next_back`
---
 arrow-row/src/lib.rs | 43 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/arrow-row/src/lib.rs b/arrow-row/src/lib.rs
index 9679c89b48..078c457477 100644
--- a/arrow-row/src/lib.rs
+++ b/arrow-row/src/lib.rs
@@ -1414,9 +1414,12 @@ impl DoubleEndedIterator for RowsIter<'_> {
         if self.end == self.start {
             return None;
         }
-        // Safety: We have checked that `start` is less than `end`
-        let row = unsafe { self.rows.row_unchecked(self.end) };
+
         self.end -= 1;
+
+        // Safety: By construction we create `end >= start`, so if `end` is 
not equal to `start` it cannot be less than `start`
+        //          therefore `end - 1` is within range
+        let row = unsafe { self.rows.row_unchecked(self.end) };
         Some(row)
     }
 }
@@ -5651,4 +5654,40 @@ mod tests {
                 .contains("not yet implemented")
         );
     }
+
+    #[test]
+    fn empty_row_iter_next_back() {
+        let rows = RowConverter::new(vec![SortField::new(DataType::UInt8)])
+            .unwrap()
+            .empty_rows(0, 0);
+        let mut rows_iter = rows.iter();
+        assert_eq!(rows_iter.next_back(), None);
+        assert_eq!(rows_iter.next_back(), None);
+        assert_eq!(rows_iter.next_back(), None);
+    }
+
+    #[test]
+    fn row_iter_next_back() {
+        let row_converter = 
RowConverter::new(vec![SortField::new(DataType::UInt8)]).unwrap();
+        let mut rng = StdRng::seed_from_u64(42);
+        let array = generate_primitive_array::<UInt8Type>(&mut rng, 100, 0.8);
+        let rows = row_converter.convert_columns(&[Arc::new(array)]).unwrap();
+
+        let mut rows_iter = rows.iter();
+        let mut bytes: Vec<u8> = vec![];
+
+        while let Some(row) = rows_iter.next_back() {
+            bytes.extend(row.data.iter().rev());
+        }
+
+        bytes.reverse();
+
+        assert_eq!(
+            bytes,
+            &rows.buffer.as_slice()[..*rows.offsets.last().unwrap()]
+        );
+
+        assert_eq!(rows_iter.next_back(), None);
+        assert_eq!(rows_iter.next(), None);
+    }
 }

Reply via email to