Skip to content

Commit 2a3fd96

Browse files
authored
RunEndBuffer review feedback (#3825)
* RunEndBuffer review feedback * Fix handling of zero-length buffers * More tests
1 parent defa599 commit 2a3fd96

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

arrow-buffer/src/buffer/run.rs

+33-9
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use crate::ArrowNativeType;
3030
/// logical array, up to that physical index.
3131
///
3232
/// Consider a [`RunEndBuffer`] containing `[3, 4, 6]`. The maximum physical index is `2`,
33-
/// as there are `3` values, and the maximum logical index is `6`, as the maximum run end
34-
/// is `6`. The physical indices are therefore `[0, 0, 0, 1, 1, 2, 2]`
33+
/// as there are `3` values, and the maximum logical index is `5`, as the maximum run end
34+
/// is `6`. The physical indices are therefore `[0, 0, 0, 1, 2, 2]`
3535
///
3636
/// ```text
3737
/// ┌─────────┐ ┌─────────┐ ┌─────────┐
@@ -41,13 +41,11 @@ use crate::ArrowNativeType;
4141
/// ├─────────┤ ├─────────┤ │ │ ├─────────┤
4242
/// │ 6 │ │ 2 │ ─┘ │ ┌──▶ │ 2 │
4343
/// └─────────┘ ├─────────┤ │ │ └─────────┘
44-
/// run ends │ 3 │ ───┤ │ physical indices
45-
/// ├─────────┤ │ │
46-
/// │ 4 │ ───┘ │
44+
/// run ends │ 3 │ ───┘ │ physical indices
4745
/// ├─────────┤ │
48-
/// │ 5 │ ─────┤
46+
/// │ 4 │ ─────┤
4947
/// ├─────────┤ │
50-
/// │ 6 │ ─────┘
48+
/// │ 5 │ ─────┘
5149
/// └─────────┘
5250
/// logical indices
5351
/// ```
@@ -90,7 +88,7 @@ where
9088
assert!(!run_ends.is_empty(), "non-empty slice but empty run-ends");
9189
let end = E::from_usize(offset.saturating_add(len)).unwrap();
9290
assert!(
93-
*run_ends.first().unwrap() >= E::usize_as(0),
91+
*run_ends.first().unwrap() > E::usize_as(0),
9492
"run-ends not greater than 0"
9593
);
9694
assert!(
@@ -169,7 +167,7 @@ where
169167

170168
/// Returns the physical index at which the logical array starts
171169
pub fn get_start_physical_index(&self) -> usize {
172-
if self.offset == 0 {
170+
if self.offset == 0 || self.len == 0 {
173171
return 0;
174172
}
175173
// Fallback to binary search
@@ -178,6 +176,9 @@ where
178176

179177
/// Returns the physical index at which the logical array ends
180178
pub fn get_end_physical_index(&self) -> usize {
179+
if self.len == 0 {
180+
return 0;
181+
}
181182
if self.max_value() == self.offset + self.len {
182183
return self.values().len() - 1;
183184
}
@@ -198,3 +199,26 @@ where
198199
}
199200
}
200201
}
202+
203+
#[cfg(test)]
204+
mod tests {
205+
use crate::buffer::RunEndBuffer;
206+
207+
#[test]
208+
fn test_zero_length_slice() {
209+
let buffer = RunEndBuffer::new(vec![1_i32, 4_i32].into(), 0, 4);
210+
assert_eq!(buffer.get_start_physical_index(), 0);
211+
assert_eq!(buffer.get_end_physical_index(), 1);
212+
assert_eq!(buffer.get_physical_index(3), 1);
213+
214+
for offset in 0..4 {
215+
let sliced = buffer.slice(offset, 0);
216+
assert_eq!(sliced.get_start_physical_index(), 0);
217+
assert_eq!(sliced.get_end_physical_index(), 0);
218+
}
219+
220+
let buffer = RunEndBuffer::new(Vec::<i32>::new().into(), 0, 0);
221+
assert_eq!(buffer.get_start_physical_index(), 0);
222+
assert_eq!(buffer.get_end_physical_index(), 0);
223+
}
224+
}

0 commit comments

Comments
 (0)