@@ -189,6 +189,39 @@ where
189189 & self . run_ends
190190 }
191191
192+ /// Similar to [`values`] but accounts for logical slicing, returning only the values
193+ /// that are part of the logical slice of this buffer.
194+ ///
195+ /// > [!WARNING]
196+ /// > The returned values are the raw physical run ends and do not account for logical
197+ /// > truncation at the slice boundaries. For example, if a run of length 10 is sliced
198+ /// > to only include the last 3 elements, the returned run end will still be the original
199+ /// > physical end. Use [`logical_run_ends`] for un-truncated, relative run ends.
200+ ///
201+ /// [`values`]: Self::values
202+ /// [`logical_run_ends`]: Self::logical_run_ends
203+ pub fn values_slice ( & self ) -> & [ E ] {
204+ let start = self . get_start_physical_index ( ) ;
205+ let end = self . get_end_physical_index ( ) ;
206+ & self . run_ends [ start..=end]
207+ }
208+
209+ /// Returns an iterator yielding run ends adjusted for the logical slice.
210+ ///
211+ /// Each yielded value is subtracted by the [`logical_offset`] and capped
212+ /// at the [`logical_length`].
213+ ///
214+ /// [`logical_offset`]: Self::offset
215+ /// [`logical_length`]: Self::len
216+ pub fn logical_run_ends ( & self ) -> impl Iterator < Item = E > + ' _ {
217+ let offset = self . logical_offset ;
218+ let len = self . logical_length ;
219+ self . values_slice ( ) . iter ( ) . map ( move |& val| {
220+ let val = val. as_usize ( ) . saturating_sub ( offset) . min ( len) ;
221+ E :: from_usize ( val) . unwrap ( )
222+ } )
223+ }
224+
192225 /// Returns the maximum run-end encoded in the underlying buffer; that is, the
193226 /// last physical run of the buffer. This does not take into account any logical
194227 /// slicing that may have occurred.
@@ -368,4 +401,65 @@ mod tests {
368401 assert_eq ! ( buffer. get_start_physical_index( ) , 0 ) ;
369402 assert_eq ! ( buffer. get_end_physical_index( ) , 0 ) ;
370403 }
404+ #[ test]
405+ fn test_sliced_buffer_access ( ) {
406+ // [0, 0, 1, 2, 2, 2]
407+ let buffer = RunEndBuffer :: new ( vec ! [ 2i32 , 3 , 6 ] . into ( ) , 0 , 6 ) ;
408+
409+ // Slice: [0, 1, 2, 2] start: 1, len: 4
410+ // Logical indices: 1, 2, 3, 4
411+ // Physical indices: 0, 1, 2, 2
412+ let sliced = buffer. slice ( 1 , 4 ) ;
413+ assert_eq ! ( sliced. get_start_physical_index( ) , 0 ) ;
414+ assert_eq ! ( sliced. get_end_physical_index( ) , 2 ) ;
415+
416+ assert_eq ! ( sliced. values_slice( ) , & [ 2 , 3 , 6 ] ) ;
417+
418+ // Slice: [2, 2] start: 3, len: 2 (relative to original)
419+ // Original indices: 4, 5
420+ // Physical indices: 2, 2
421+ let sliced2 = buffer. slice ( 4 , 2 ) ;
422+ assert_eq ! ( sliced2. get_start_physical_index( ) , 2 ) ;
423+ assert_eq ! ( sliced2. get_end_physical_index( ) , 2 ) ;
424+ assert_eq ! ( sliced2. values_slice( ) , & [ 6 ] ) ;
425+
426+ // Test with offset slice
427+ // buffer: [2, 3, 6] (logical length 6)
428+ // slice(1, 4) -> [0, 1, 2, 2] (logical length 4). Offset 1.
429+ // Indices: 0 (orig 1) -> phys 0
430+ // Indices: 1 (orig 2) -> phys 1
431+ // Indices: 2 (orig 3) -> phys 2
432+ // Indices: 3 (orig 4) -> phys 2
433+
434+ // slice(3, 1) on sliced buffer.
435+ // indices 3 (orig 4). phys 2.
436+ let sliced3 = sliced. slice ( 3 , 1 ) ;
437+ assert_eq ! ( sliced3. get_start_physical_index( ) , 2 ) ;
438+ assert_eq ! ( sliced3. get_end_physical_index( ) , 2 ) ;
439+ assert_eq ! ( sliced3. values_slice( ) , & [ 6 ] ) ;
440+ }
441+
442+ #[ test]
443+ fn test_logical_run_ends ( ) {
444+ // [0, 0, 1, 2, 2, 2]
445+ let buffer = RunEndBuffer :: new ( vec ! [ 2i32 , 3 , 6 ] . into ( ) , 0 , 6 ) ;
446+
447+ // Slice: [0, 1, 2, 2] start: 1, len: 4
448+ // Logical indices: 1, 2, 3, 4
449+ // Original run ends: [2, 3, 6]
450+ // Adjusted: [2-1, 3-1, 6-1] capped at 4 -> [1, 2, 4]
451+ let sliced = buffer. slice ( 1 , 4 ) ;
452+ let logical_run_ends: Vec < i32 > = sliced. logical_run_ends ( ) . collect ( ) ;
453+ assert_eq ! ( logical_run_ends, & [ 1 , 2 , 4 ] ) ;
454+ assert_eq ! ( sliced. values_slice( ) , & [ 2 , 3 , 6 ] ) ; //This shows how values_slice are different than logical run ends
455+
456+ // Slice: [2, 2] start: 4, len: 2
457+ // Original run ends: [2, 3, 6]
458+ // Slicing at 4 means we only have the last run (physical index 2, which ends at 6)
459+ // Adjusted: [6-4] capped at 2 -> [2]
460+ let sliced = buffer. slice ( 4 , 2 ) ;
461+ let logical_run_ends: Vec < i32 > = sliced. logical_run_ends ( ) . collect ( ) ;
462+ assert_eq ! ( logical_run_ends, & [ 2 ] ) ;
463+ assert_eq ! ( sliced. values_slice( ) , & [ 6 ] ) ; // This shows how values_slice are different than logical run ends
464+ }
371465}
0 commit comments