1use crate::buffer::ScalarBuffer;
19use crate::{ArrowNativeType, MutableBuffer, NullBuffer, OffsetBufferBuilder};
20use std::ops::Deref;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct OffsetBuffer<O: ArrowNativeType>(ScalarBuffer<O>);
60
61impl<O: ArrowNativeType> OffsetBuffer<O> {
62 pub fn new(buffer: ScalarBuffer<O>) -> Self {
69 assert!(!buffer.is_empty(), "offsets cannot be empty");
70 assert!(
71 buffer[0] >= O::usize_as(0),
72 "offsets must be greater than 0"
73 );
74 assert!(
75 buffer.windows(2).all(|w| w[0] <= w[1]),
76 "offsets must be monotonically increasing"
77 );
78 Self(buffer)
79 }
80
81 pub unsafe fn new_unchecked(buffer: ScalarBuffer<O>) -> Self {
88 Self(buffer)
89 }
90
91 pub fn new_empty() -> Self {
93 let buffer = MutableBuffer::from_len_zeroed(std::mem::size_of::<O>());
94 Self(buffer.into_buffer().into())
95 }
96
97 pub fn new_zeroed(len: usize) -> Self {
99 let len_bytes = len
100 .checked_add(1)
101 .and_then(|o| o.checked_mul(std::mem::size_of::<O>()))
102 .expect("overflow");
103 let buffer = MutableBuffer::from_len_zeroed(len_bytes);
104 Self(buffer.into_buffer().into())
105 }
106
107 pub fn from_lengths<I>(lengths: I) -> Self
122 where
123 I: IntoIterator<Item = usize>,
124 {
125 let iter = lengths.into_iter();
126 let mut out = Vec::with_capacity(iter.size_hint().0 + 1);
127 out.push(O::usize_as(0));
128
129 let mut acc = 0_usize;
130 for length in iter {
131 acc = acc.checked_add(length).expect("usize overflow");
132 out.push(O::usize_as(acc))
133 }
134 O::from_usize(acc).expect("offset overflow");
136 Self(out.into())
137 }
138
139 pub fn from_repeated_length(length: usize, n: usize) -> Self {
154 if n == 0 {
155 return Self::new_empty();
156 }
157
158 if length == 0 {
159 return Self::new_zeroed(n);
160 }
161
162 length.checked_mul(n).expect("usize overflow");
165
166 O::from_usize(length * n).expect("offset overflow");
168
169 let offsets = (0..=n)
170 .map(|index| O::usize_as(index * length))
171 .collect::<Vec<O>>();
172
173 Self(ScalarBuffer::from(offsets))
174 }
175
176 pub fn lengths(&self) -> impl ExactSizeIterator<Item = usize> + '_ {
205 self.0.windows(2).map(|x| x[1].as_usize() - x[0].as_usize())
206 }
207
208 pub fn shrink_to_fit(&mut self) {
210 self.0.shrink_to_fit();
211 }
212
213 pub fn inner(&self) -> &ScalarBuffer<O> {
215 &self.0
216 }
217
218 pub fn into_inner(self) -> ScalarBuffer<O> {
220 self.0
221 }
222
223 #[cfg(feature = "pool")]
225 pub fn claim(&self, pool: &dyn crate::MemoryPool) {
226 self.0.claim(pool);
227 }
228
229 pub fn slice(&self, offset: usize, len: usize) -> Self {
231 Self(self.0.slice(offset, len.saturating_add(1)))
232 }
233
234 #[inline]
238 pub fn ptr_eq(&self, other: &Self) -> bool {
239 self.0.ptr_eq(&other.0)
240 }
241
242 pub fn has_non_empty_nulls(&self, null_buffer: Option<&NullBuffer>) -> bool {
278 let Some(null_buffer) = null_buffer else {
279 return false;
280 };
281
282 assert_eq!(
283 self.len() - 1,
284 null_buffer.len(),
285 "The length of the offsets should be 1 more than the length of the null buffer"
286 );
287
288 if null_buffer.null_count() == 0 {
289 return false;
290 }
291
292 let initial_offset = self[0];
294 let last_offset = self[self.len() - 1];
295
296 if null_buffer.null_count() == self.len() - 1 {
298 return last_offset != initial_offset;
299 }
300
301 let mut valid_slices_iter = null_buffer.valid_slices();
302
303 let (start, end) = valid_slices_iter.next().unwrap();
305
306 if self[start] != initial_offset {
308 return true;
309 }
310
311 let mut end_offset_of_last_valid_value = self[end];
314
315 for (start, end) in valid_slices_iter {
316 if self[start] != end_offset_of_last_valid_value {
319 return true;
320 }
321
322 end_offset_of_last_valid_value = self[end];
325 }
326
327 end_offset_of_last_valid_value != last_offset
328 }
329
330 pub fn subtract(self, rhs: O) -> Self
350 where
351 O: std::ops::Sub<Output = O> + std::cmp::PartialOrd + num_traits::CheckedSub,
352 {
353 if rhs == O::usize_as(0) {
354 return self;
355 }
356
357 let len = self.len();
358
359 assert!(
361 self[0] >= rhs,
362 "shifted offsets will become negative which is not allowed"
363 );
364
365 if rhs < O::usize_as(0) {
367 self[len - 1].checked_sub(&rhs).expect("must not overflow");
368 }
369
370 let shifted_offsets: Vec<O> = match self.into_inner().into_inner().into_vec() {
372 Ok(mut v) => {
374 for offset in v.iter_mut() {
375 *offset = *offset - rhs;
376 }
377 v
378 }
379 Err(buffer) => {
381 let offsets = ScalarBuffer::<O>::from(buffer);
382 offsets.iter().map(|offset| *offset - rhs).collect()
383 }
384 };
385 let shifted_buffer = ScalarBuffer::from(shifted_offsets);
386 unsafe { Self::new_unchecked(shifted_buffer) }
391 }
392}
393
394impl<T: ArrowNativeType> Deref for OffsetBuffer<T> {
395 type Target = [T];
396
397 #[inline]
398 fn deref(&self) -> &Self::Target {
399 &self.0
400 }
401}
402
403impl<T: ArrowNativeType> AsRef<[T]> for OffsetBuffer<T> {
404 #[inline]
405 fn as_ref(&self) -> &[T] {
406 self
407 }
408}
409
410impl<O: ArrowNativeType> From<OffsetBufferBuilder<O>> for OffsetBuffer<O> {
411 fn from(value: OffsetBufferBuilder<O>) -> Self {
412 value.finish()
413 }
414}
415
416impl<O: ArrowNativeType> Default for OffsetBuffer<O> {
417 fn default() -> Self {
418 Self::new_empty()
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 #[should_panic(expected = "offsets cannot be empty")]
428 fn empty_offsets() {
429 OffsetBuffer::new(Vec::<i32>::new().into());
430 }
431
432 #[test]
433 #[should_panic(expected = "offsets must be greater than 0")]
434 fn negative_offsets() {
435 OffsetBuffer::new(vec![-1, 0, 1].into());
436 }
437
438 #[test]
439 fn offsets() {
440 OffsetBuffer::new(vec![0, 1, 2, 3].into());
441
442 let offsets = OffsetBuffer::<i32>::new_zeroed(3);
443 assert_eq!(offsets.as_ref(), &[0; 4]);
444
445 let offsets = OffsetBuffer::<i32>::new_zeroed(0);
446 assert_eq!(offsets.as_ref(), &[0; 1]);
447 }
448
449 #[test]
450 #[should_panic(expected = "overflow")]
451 fn offsets_new_zeroed_overflow() {
452 OffsetBuffer::<i32>::new_zeroed(usize::MAX);
453 }
454
455 #[test]
456 #[should_panic(expected = "offsets must be monotonically increasing")]
457 fn non_monotonic_offsets() {
458 OffsetBuffer::new(vec![1, 2, 0].into());
459 }
460
461 #[test]
462 fn from_lengths() {
463 let buffer = OffsetBuffer::<i32>::from_lengths([2, 6, 3, 7, 2]);
464 assert_eq!(buffer.as_ref(), &[0, 2, 8, 11, 18, 20]);
465
466 let half_max = i32::MAX / 2;
467 let buffer = OffsetBuffer::<i32>::from_lengths([half_max as usize, half_max as usize]);
468 assert_eq!(buffer.as_ref(), &[0, half_max, half_max * 2]);
469 }
470
471 #[test]
472 #[should_panic(expected = "offset overflow")]
473 fn from_lengths_offset_overflow() {
474 OffsetBuffer::<i32>::from_lengths([i32::MAX as usize, 1]);
475 }
476
477 #[test]
478 #[should_panic(expected = "usize overflow")]
479 fn from_lengths_usize_overflow() {
480 OffsetBuffer::<i32>::from_lengths([usize::MAX, 1]);
481 }
482
483 #[test]
484 #[should_panic(expected = "offset overflow")]
485 fn from_repeated_lengths_offset_length_overflow() {
486 OffsetBuffer::<i32>::from_repeated_length(i32::MAX as usize / 4, 5);
487 }
488
489 #[test]
490 #[should_panic(expected = "offset overflow")]
491 fn from_repeated_lengths_offset_repeat_overflow() {
492 OffsetBuffer::<i32>::from_repeated_length(1, i32::MAX as usize + 1);
493 }
494
495 #[test]
496 #[should_panic(expected = "offset overflow")]
497 fn from_repeated_lengths_usize_length_overflow() {
498 OffsetBuffer::<i32>::from_repeated_length(usize::MAX, 1);
499 }
500
501 #[test]
502 #[should_panic(expected = "usize overflow")]
503 fn from_repeated_lengths_usize_length_usize_overflow() {
504 OffsetBuffer::<i32>::from_repeated_length(usize::MAX, 2);
505 }
506
507 #[test]
508 #[should_panic(expected = "offset overflow")]
509 fn from_repeated_lengths_usize_repeat_overflow() {
510 OffsetBuffer::<i32>::from_repeated_length(1, usize::MAX);
511 }
512
513 #[test]
514 fn get_lengths() {
515 let offsets = OffsetBuffer::<i32>::new(ScalarBuffer::<i32>::from(vec![0, 1, 4, 9]));
516 assert_eq!(offsets.lengths().collect::<Vec<usize>>(), vec![1, 3, 5]);
517 }
518
519 #[test]
520 fn get_lengths_should_be_with_fixed_size() {
521 let offsets = OffsetBuffer::<i32>::new(ScalarBuffer::<i32>::from(vec![0, 1, 4, 9]));
522 let iter = offsets.lengths();
523 assert_eq!(iter.size_hint(), (3, Some(3)));
524 assert_eq!(iter.len(), 3);
525 }
526
527 #[test]
528 fn get_lengths_from_empty_offset_buffer_should_be_empty_iterator() {
529 let offsets = OffsetBuffer::<i32>::new_empty();
530 assert_eq!(offsets.lengths().collect::<Vec<usize>>(), vec![]);
531 }
532
533 #[test]
534 fn impl_eq() {
535 fn are_equal<T: Eq>(a: &T, b: &T) -> bool {
536 a.eq(b)
537 }
538
539 assert!(
540 are_equal(
541 &OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 1, 4, 9])),
542 &OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 1, 4, 9]))
543 ),
544 "OffsetBuffer should implement Eq."
545 );
546 }
547
548 #[test]
549 fn impl_default() {
550 let default = OffsetBuffer::<i32>::default();
551 assert_eq!(default.as_ref(), &[0]);
552 }
553
554 #[test]
555 fn from_repeated_length_basic() {
556 let buffer = OffsetBuffer::<i32>::from_repeated_length(4, 3);
558 assert_eq!(buffer.as_ref(), &[0, 4, 8, 12]);
559
560 let lengths: Vec<usize> = buffer.lengths().collect();
562 assert_eq!(lengths, vec![4, 4, 4]);
563 }
564
565 #[test]
566 fn from_repeated_length_single_repeat() {
567 let buffer = OffsetBuffer::<i32>::from_repeated_length(5, 1);
569 assert_eq!(buffer.as_ref(), &[0, 5]);
570
571 let lengths: Vec<usize> = buffer.lengths().collect();
572 assert_eq!(lengths, vec![5]);
573 }
574
575 #[test]
576 fn from_repeated_length_zero_repeats() {
577 let buffer = OffsetBuffer::<i32>::from_repeated_length(10, 0);
578 assert_eq!(buffer, OffsetBuffer::<i32>::new_empty());
579 }
580
581 #[test]
582 fn from_repeated_length_zero_length() {
583 let buffer = OffsetBuffer::<i32>::from_repeated_length(0, 5);
585 assert_eq!(buffer.as_ref(), &[0, 0, 0, 0, 0, 0]);
586
587 let lengths: Vec<usize> = buffer.lengths().collect();
589 assert_eq!(lengths, vec![0, 0, 0, 0, 0]);
590 }
591
592 #[test]
593 fn from_repeated_length_large_values() {
594 let buffer = OffsetBuffer::<i32>::from_repeated_length(1000, 100);
596 assert_eq!(buffer[0], 0);
597
598 let lengths: Vec<usize> = buffer.lengths().collect();
600 assert_eq!(lengths.len(), 100);
601 assert!(lengths.iter().all(|&len| len == 1000));
602 }
603
604 #[test]
605 fn from_repeated_length_unit_length() {
606 let buffer = OffsetBuffer::<i32>::from_repeated_length(1, 10);
608 assert_eq!(buffer.as_ref(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
609
610 let lengths: Vec<usize> = buffer.lengths().collect();
611 assert_eq!(lengths, vec![1; 10]);
612 }
613
614 #[test]
615 fn from_repeated_length_max_safe_values() {
616 let third_max = (i32::MAX / 3) as usize;
619 let buffer = OffsetBuffer::<i32>::from_repeated_length(third_max, 2);
620 assert_eq!(
621 buffer.as_ref(),
622 &[0, third_max as i32, (third_max * 2) as i32]
623 );
624 }
625
626 #[test]
631 fn has_non_empty_nulls_none_null_buffer() {
632 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 5, 8]));
634 assert!(!offsets.has_non_empty_nulls(None));
635 }
636
637 #[test]
638 fn has_non_empty_nulls_all_valid() {
639 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 5, 8]));
641 let nulls = NullBuffer::new_valid(3);
642 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
643 }
644
645 #[test]
646 fn has_non_empty_nulls_all_null_empty_offsets() {
647 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 0, 0]));
649 let nulls = NullBuffer::new_null(3);
650 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
651 }
652
653 #[test]
654 fn has_non_empty_nulls_all_null_non_empty_offsets() {
655 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 2, 5, 7]));
657 let nulls = NullBuffer::new_null(3);
658 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
659 }
660
661 #[test]
662 fn has_non_empty_nulls_all_null_nonzero_but_equal_offsets() {
663 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![5, 5, 5]));
665 let nulls = NullBuffer::new_null(2);
666 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
667 }
668
669 #[test]
670 fn has_non_empty_nulls_leading_nulls_with_data() {
671 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 5, 8]));
675 let nulls = NullBuffer::from(vec![false, true, true]);
676 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
677 }
678
679 #[test]
680 fn has_non_empty_nulls_leading_nulls_without_data() {
681 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 6]));
685 let nulls = NullBuffer::from(vec![false, true, true]);
686 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
687 }
688
689 #[test]
690 fn has_non_empty_nulls_only_trailing_null_has_data() {
691 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 6, 8]));
695 let nulls = NullBuffer::from(vec![false, true, true, false]);
696 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
697 }
698
699 #[test]
700 fn has_non_empty_nulls_trailing_nulls_without_data() {
701 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6, 6]));
705 let nulls = NullBuffer::from(vec![true, true, false]);
706 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
707 }
708
709 #[test]
710 fn has_non_empty_nulls_middle_nulls_with_data() {
711 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 7, 10]));
715 let nulls = NullBuffer::from(vec![true, false, true]);
716 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
717 }
718
719 #[test]
720 fn has_non_empty_nulls_middle_nulls_without_data() {
721 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 3, 6]));
725 let nulls = NullBuffer::from(vec![true, false, true]);
726 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
727 }
728
729 #[test]
730 fn has_non_empty_nulls_alternating_null_valid_all_empty() {
731 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 3, 6, 6]));
735 let nulls = NullBuffer::from(vec![false, true, false, true, false]);
736 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
737
738 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 3, 6, 6, 9]));
740 let nulls = NullBuffer::from(vec![false, true, false, true, false, true]);
741 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
742 }
743
744 #[test]
745 fn has_non_empty_nulls_multiple_null_regions_second_has_data() {
746 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 5, 6]));
750 let nulls = NullBuffer::from(vec![false, true, false, true]);
751 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
752 }
753
754 #[test]
755 fn has_non_empty_nulls_multiple_null_regions_later_gap_has_data() {
756 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0, 3, 3, 6, 8, 10]));
763 let nulls = NullBuffer::from(vec![false, true, false, true, false, true]);
764 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
765 }
766
767 #[test]
768 fn has_non_empty_nulls_single_element_null_empty() {
769 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 0]));
771 let nulls = NullBuffer::new_null(1);
772 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
773 }
774
775 #[test]
776 fn has_non_empty_nulls_single_element_null_non_empty() {
777 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 5]));
779 let nulls = NullBuffer::new_null(1);
780 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
781 }
782
783 #[test]
784 fn has_non_empty_nulls_single_element_valid() {
785 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 5]));
787 let nulls = NullBuffer::new_valid(1);
788 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
789 }
790
791 #[test]
792 fn has_non_empty_nulls_consecutive_nulls_between_valid_slices() {
793 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 2, 2, 2, 5, 8]));
798 let nulls = NullBuffer::from(vec![true, false, false, true, true]);
799 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
800 }
801
802 #[test]
803 fn has_non_empty_nulls_consecutive_nulls_between_valid_slices_with_data() {
804 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 2, 3, 4, 5, 8]));
811 let nulls = NullBuffer::from(vec![true, false, false, true, true]);
812 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
813 }
814
815 #[test]
816 fn has_non_empty_nulls_nonzero_initial_offset_all_null_equal() {
817 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![10, 10, 10]));
819 let nulls = NullBuffer::new_null(2);
820 assert!(!offsets.has_non_empty_nulls(Some(&nulls)));
821 }
822
823 #[test]
824 fn has_non_empty_nulls_nonzero_initial_offset_with_data() {
825 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![10, 15, 20]));
829 let nulls = NullBuffer::from(vec![false, true]);
830 assert!(offsets.has_non_empty_nulls(Some(&nulls)));
831 }
832
833 #[test]
834 fn has_non_empty_nulls_sliced_no_nulls_in_null_region() {
835 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 3, 6, 6, 9]));
839 let sliced = offsets.slice(1, 3);
840 let nulls = NullBuffer::from(vec![false, true, false]);
841 assert!(!sliced.has_non_empty_nulls(Some(&nulls)));
842 }
843
844 #[test]
845 fn has_non_empty_nulls_sliced_null_has_data() {
846 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 7, 10, 15]));
850 let sliced = offsets.slice(1, 2);
851 let nulls = NullBuffer::from(vec![false, true]);
852 assert!(sliced.has_non_empty_nulls(Some(&nulls)));
853 }
854
855 #[test]
856 #[should_panic(
857 expected = "The length of the offsets should be 1 more than the length of the null buffer"
858 )]
859 fn has_non_empty_nulls_all_valid_mismatched_lengths_too_short() {
860 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 5, 8]));
862 let nulls = NullBuffer::new_valid(2); offsets.has_non_empty_nulls(Some(&nulls));
864 }
865
866 #[test]
867 #[should_panic(
868 expected = "The length of the offsets should be 1 more than the length of the null buffer"
869 )]
870 fn has_non_empty_nulls_all_valid_mismatched_lengths_too_long() {
871 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 5, 8]));
873 let nulls = NullBuffer::new_valid(5); offsets.has_non_empty_nulls(Some(&nulls));
875 }
876
877 #[test]
878 #[should_panic(expected = "shifted offsets will become negative which is not allowed")]
879 fn should_panic_for_subtract_by_value_that_will_cause_offsets_to_be_less_than_zero() {
880 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6]));
882 offsets.subtract(1);
883 }
884
885 #[test]
886 fn subtract_by_value_that_will_cause_offsets_to_be_less_than_zero_for_outside_the_slice() {
887 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 1, 4, 7]));
888 let sliced = offsets.slice(1, 2); drop(offsets);
890 assert_eq!(sliced.as_ref(), &[1, 4, 7]);
891
892 let result = sliced.subtract(1);
893 assert_eq!(result.as_ref(), &[0, 3, 6]);
894 assert_eq!(result.len(), 3);
895 }
896
897 #[test]
898 #[should_panic(expected = "must not overflow")]
899 fn should_panic_subtract_by_value_that_will_cause_offsets_to_overflow() {
900 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 5, i32::MAX]));
903 offsets.subtract(-1);
904 }
905
906 #[test]
907 fn subtract_by_value_that_will_cause_offsets_to_overflow_outside_the_slice() {
908 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6, i32::MAX]));
909 let sliced = offsets.slice(0, 2); assert_eq!(sliced.as_ref(), &[0, 3, 6]);
911
912 let result = sliced.subtract(-1);
913 assert_eq!(result.as_ref(), &[1, 4, 7]);
914 assert_eq!(result.len(), 3);
915 }
916
917 #[test]
918 fn when_shift_is_0_subtract_should_reuse_the_buffer_even_when_it_is_shared() {
919 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6]));
922 let shared = offsets.clone(); let result = offsets.subtract(0);
924 assert!(
925 result.ptr_eq(&shared),
926 "subtract(0) must return the same underlying buffer, even when shared"
927 );
928 }
929
930 #[test]
931 fn should_reuse_the_underline_data_when_the_buffer_is_not_shared() {
932 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![2, 5, 8]));
935 let ptr_before = offsets.as_ptr();
936 let result = offsets.subtract(2);
937 assert_eq!(
938 ptr_before,
939 result.as_ptr(),
940 "a non-shared buffer should be mutated in place, reusing the allocation"
941 );
942 assert_eq!(result.as_ref(), &[0, 3, 6]);
943 }
944
945 #[test]
946 fn should_create_a_new_buffer_when_the_buffer_is_shared() {
947 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![2, 5, 8]));
948 let shared = offsets.clone();
949 let ptr_before = offsets.as_ptr();
950 let result = offsets.subtract(2);
951 assert_ne!(
952 ptr_before,
953 result.as_ptr(),
954 "a shared buffer must not be mutated in place; a new allocation is created"
955 );
956 assert_eq!(result.as_ref(), &[0, 3, 6]);
957 assert_eq!(shared.as_ref(), &[2, 5, 8]);
959 }
960
961 #[test]
962 fn when_shift_is_negative_it_should_shift_offsets_in_the_right_direction() {
963 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6]));
965 let result = offsets.subtract(-2);
966 assert_eq!(result.as_ref(), &[2, 5, 8]);
967 }
968
969 #[test]
971 fn for_sliced_unshared_buffer_shift_should_not_reuse_buffer() {
972 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![1, 3, 6, 9, 12]));
974 let sliced = offsets.slice(1, 2); drop(offsets); assert_eq!(sliced.as_ref(), &[3, 6, 9]);
977
978 let ptr_before = sliced.as_ptr();
979 let result = sliced.subtract(1);
980
981 assert_ne!(
982 ptr_before,
983 result.as_ptr(),
984 "should not be reused until #10118 is merged"
985 );
986
987 assert_eq!(result.as_ref(), &[2, 5, 8]);
988 }
989
990 #[test]
991 fn for_sliced_but_start_at_0_unshared_buffer_shift_should_reuse_buffer() {
992 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![1, 3, 6, 9, 12]));
993 let sliced = offsets.slice(0, 2);
994 drop(offsets); assert_eq!(sliced.as_ref(), &[1, 3, 6]);
996
997 let ptr_before = sliced.as_ptr();
998 let result = sliced.subtract(1);
999
1000 assert_eq!(ptr_before, result.as_ptr(), "should be reused");
1001
1002 assert_eq!(result.as_ref(), &[0, 2, 5]);
1003 }
1004
1005 #[test]
1006 fn for_sliced_shared_buffer_shifted_buffer_should_only_include_the_sliced_data() {
1007 let offsets = OffsetBuffer::new(ScalarBuffer::<i32>::from(vec![0, 3, 6, 9, 12]));
1012 let sliced = offsets.slice(1, 2);
1013 assert_eq!(sliced.as_ref(), &[3, 6, 9]);
1014
1015 let result = sliced.subtract(3);
1016
1017 assert_eq!(
1018 result.as_ref(),
1019 &[0, 3, 6],
1020 "shifted result should contain only the sliced data"
1021 );
1022 assert_eq!(result.len(), 3);
1023
1024 let underlying_buffer = result.inner().inner();
1026 assert_eq!(underlying_buffer.ptr_offset(), 0);
1027 assert_eq!(underlying_buffer.len(), 3 * std::mem::size_of::<i32>());
1028 }
1029}