1#[cfg(feature = "proptest")]
20use proptest_derive::Arbitrary;
21use serde::{Deserialize, Serialize};
22use std::ops::{Add, AddAssign, Div, Mul, Neg, Rem, Sub, SubAssign};
23
24#[derive(
37 Debug,
38 Default,
39 Ord,
40 PartialOrd,
41 Eq,
42 PartialEq,
43 Copy,
44 Clone,
45 Serialize,
46 Deserialize
47)]
48#[cfg_attr(feature = "proptest", derive(Arbitrary))]
49pub struct Overflowing<T>(T);
50
51#[derive(Debug)]
53pub enum OverflowingBehavior {
54 Panic,
56 SoftPanic,
58 Ignore,
60}
61
62impl std::str::FromStr for OverflowingBehavior {
63 type Err = String;
64
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 match s {
67 _ if s.eq_ignore_ascii_case("panic") => Ok(OverflowingBehavior::Panic),
68 _ if s.eq_ignore_ascii_case("soft_panic") => Ok(OverflowingBehavior::SoftPanic),
69 _ if s.eq_ignore_ascii_case("ignore") => Ok(OverflowingBehavior::Ignore),
70 _ => Err(format!("Invalid OverflowingBehavior: {s}")),
71 }
72 }
73}
74
75pub fn set_behavior(behavior: OverflowingBehavior) {
81 overflowing_support::set_overflowing_mode(behavior);
82}
83
84impl<T> Overflowing<T> {
85 pub fn into_inner(self) -> T {
87 self.0
88 }
89}
90
91impl<T: std::fmt::Display> std::fmt::Display for Overflowing<T> {
92 #[inline(always)]
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 self.0.fmt(f)
95 }
96}
97
98#[cfg(feature = "columnar")]
99mod columnar {
100 use crate::overflowing::Overflowing;
101 use columnar::bytes::indexed::DecodedStore;
102 use columnar::common::PushIndexAs;
103 use columnar::{
104 AsBytes, Borrow, Clear, Columnar, Container, FromBytes, Index, IndexAs, Len, Push,
105 };
106 use serde::{Deserialize, Serialize};
107 use std::ops::Range;
108
109 impl<T: Columnar<Container: PushIndexAs<T>> + Copy + Send> Columnar for Overflowing<T>
110 where
111 Overflowing<T>: From<T>,
112 {
113 #[inline(always)]
114 fn into_owned(other: columnar::Ref<'_, Self>) -> Self {
115 other
116 }
117 type Container = Overflows<T, T::Container>;
118 #[inline(always)]
119 fn reborrow<'b, 'a: 'b>(thing: columnar::Ref<'a, Self>) -> columnar::Ref<'b, Self>
120 where
121 Self: 'a,
122 {
123 thing
124 }
125 }
126
127 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
131 pub struct Overflows<T, TC>(TC, std::marker::PhantomData<T>);
132
133 impl<T, TC: Default> Default for Overflows<T, TC> {
134 #[inline(always)]
135 fn default() -> Self {
136 Self(TC::default(), std::marker::PhantomData)
137 }
138 }
139
140 impl<T: Columnar + Copy + Send, TC: PushIndexAs<T>> Borrow for Overflows<T, TC>
141 where
142 Overflowing<T>: From<T>,
143 {
144 type Ref<'a> = Overflowing<T>;
145 type Borrowed<'a>
146 = Overflows<T, TC::Borrowed<'a>>
147 where
148 Self: 'a;
149 #[inline(always)]
150 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
151 Overflows(self.0.borrow(), std::marker::PhantomData)
152 }
153 #[inline(always)]
154 fn reborrow<'b, 'a: 'b>(item: Self::Borrowed<'a>) -> Self::Borrowed<'b>
155 where
156 Self: 'a,
157 {
158 Overflows(TC::reborrow(item.0), std::marker::PhantomData)
159 }
160
161 #[inline(always)]
162 fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>
163 where
164 Self: 'a,
165 {
166 item
167 }
168 }
169
170 impl<T: Columnar + Copy + Send, TC: PushIndexAs<T>> Container for Overflows<T, TC>
171 where
172 Overflowing<T>: From<T>,
173 {
174 #[inline(always)]
175 fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: Range<usize>) {
176 self.0.extend_from_self(other.0, range);
177 }
178 #[inline(always)]
179 fn reserve_for<'a, I>(&mut self, selves: I)
180 where
181 Self: 'a,
182 I: Iterator<Item = Self::Borrowed<'a>> + Clone,
183 {
184 self.0.reserve_for(selves.map(|s| s.0));
185 }
186 }
187
188 impl<'a, T: Copy, TC: AsBytes<'a>> AsBytes<'a> for Overflows<T, TC> {
189 const SLICE_COUNT: usize = TC::SLICE_COUNT;
190 #[inline(always)]
191 fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
192 self.0.get_byte_slice(index)
193 }
194 #[inline(always)]
195 fn as_bytes(&self) -> impl Iterator<Item = (u64, &'a [u8])> {
196 self.0.as_bytes()
197 }
198 }
199
200 impl<'a, T: Copy, TC: FromBytes<'a>> FromBytes<'a> for Overflows<T, TC> {
201 const SLICE_COUNT: usize = TC::SLICE_COUNT;
202 #[inline(always)]
203 fn from_bytes(bytes: &mut impl Iterator<Item = &'a [u8]>) -> Self {
204 Self(TC::from_bytes(bytes), std::marker::PhantomData)
205 }
206 #[inline(always)]
207 fn from_store(store: &DecodedStore<'a>, offset: &mut usize) -> Self {
208 Self(TC::from_store(store, offset), std::marker::PhantomData)
209 }
210 fn element_sizes(sizes: &mut Vec<usize>) -> Result<(), String> {
211 TC::element_sizes(sizes)
212 }
213 }
214
215 impl<T: Copy, TC: Len> Len for Overflows<T, TC> {
216 #[inline(always)]
217 fn len(&self) -> usize {
218 self.0.len()
219 }
220 }
221
222 impl<T: Copy, TC: Clear> Clear for Overflows<T, TC> {
223 #[inline(always)]
224 fn clear(&mut self) {
225 self.0.clear();
226 }
227 }
228
229 impl<T: Copy, TC: IndexAs<T>> Index for Overflows<T, TC>
230 where
231 Overflowing<T>: From<T>,
232 {
233 type Ref = Overflowing<T>;
234 #[inline(always)]
235 fn get(&self, index: usize) -> Self::Ref {
236 self.0.index_as(index).into()
237 }
238 }
239
240 impl<T: Copy, TC: for<'a> Push<&'a T>> Push<Overflowing<T>> for Overflows<T, TC> {
241 #[inline(always)]
242 fn push(&mut self, item: Overflowing<T>) {
243 self.0.push(&item.0);
244 }
245 }
246
247 impl<T: Copy, TC: for<'a> Push<&'a T>> Push<&Overflowing<T>> for Overflows<T, TC> {
248 #[inline(always)]
249 fn push(&mut self, item: &Overflowing<T>) {
250 self.0.push(&item.0);
251 }
252 }
253}
254
255macro_rules! impl_overflowing {
256 ($t:ty) => {
257 impl Overflowing<$t> {
258 pub const ZERO: Self = Self(0);
260 pub const ONE: Self = Self(1);
262 pub const MIN: Self = Self(<$t>::MIN);
264 pub const MAX: Self = Self(<$t>::MAX);
266
267 #[inline(always)]
269 pub fn checked_add(self, rhs: Self) -> Option<Self> {
270 self.0.checked_add(rhs.0).map(Self)
271 }
272
273 #[inline(always)]
275 pub fn wrapping_add(self, rhs: Self) -> Self {
276 Self(self.0.wrapping_add(rhs.0))
277 }
278
279 #[inline(always)]
281 pub fn checked_mul(self, rhs: Self) -> Option<Self> {
282 self.0.checked_mul(rhs.0).map(Self)
283 }
284
285 #[inline(always)]
287 pub fn wrapping_mul(self, rhs: Self) -> Self {
288 Self(self.0.wrapping_mul(rhs.0))
289 }
290
291 pub fn is_zero(self) -> bool {
293 self == Self::ZERO
294 }
295 }
296
297 impl Add<Self> for Overflowing<$t> {
298 type Output = Self;
299
300 #[inline(always)]
301 fn add(self, rhs: Self) -> Self::Output {
302 match self.0.overflowing_add(rhs.0) {
303 (result, true) => {
304 overflowing_support::handle_overflow(result, format_args!("{self} + {rhs}"))
305 }
306 (result, false) => Self(result),
307 }
308 }
309 }
310
311 impl<'a> Add<&'a Self> for Overflowing<$t> {
312 type Output = Self;
313
314 #[inline(always)]
315 fn add(self, rhs: &'a Self) -> Self::Output {
316 match self.0.overflowing_add(rhs.0) {
317 (result, true) => {
318 overflowing_support::handle_overflow(result, format_args!("{self} + {rhs}"))
319 }
320 (result, false) => Self(result),
321 }
322 }
323 }
324
325 impl AddAssign<Self> for Overflowing<$t> {
326 #[inline(always)]
327 fn add_assign(&mut self, rhs: Self) {
328 *self = *self + rhs;
329 }
330 }
331
332 impl AddAssign<&Self> for Overflowing<$t> {
333 #[inline(always)]
334 fn add_assign(&mut self, rhs: &Self) {
335 *self = *self + *rhs;
336 }
337 }
338
339 impl Div<Self> for Overflowing<$t> {
340 type Output = Overflowing<<$t as Div>::Output>;
341
342 #[inline(always)]
343 fn div(self, rhs: Self) -> Self::Output {
344 match self.0.overflowing_div(rhs.0) {
345 (result, true) => {
346 overflowing_support::handle_overflow(result, format_args!("{self} / {rhs}"))
347 }
348 (result, false) => Self(result),
349 }
350 }
351 }
352
353 impl Rem<Self> for Overflowing<$t> {
354 type Output = Overflowing<<$t as Rem>::Output>;
355
356 #[inline(always)]
357 fn rem(self, rhs: Self) -> Self::Output {
358 match self.0.overflowing_rem(rhs.0) {
359 (result, true) => {
360 overflowing_support::handle_overflow(result, format_args!("{self} % {rhs}"))
361 }
362 (result, false) => Self(result),
363 }
364 }
365 }
366
367 impl Sub<Self> for Overflowing<$t> {
368 type Output = Self;
369
370 #[inline(always)]
371 fn sub(self, rhs: Self) -> Self::Output {
372 match self.0.overflowing_sub(rhs.0) {
373 (result, true) => {
374 overflowing_support::handle_overflow(result, format_args!("{self} - {rhs}"))
375 }
376 (result, false) => Self(result),
377 }
378 }
379 }
380
381 impl<'a> Sub<&'a Self> for Overflowing<$t> {
382 type Output = Self;
383
384 #[inline(always)]
385 fn sub(self, rhs: &'a Self) -> Self::Output {
386 match self.0.overflowing_sub(rhs.0) {
387 (result, true) => {
388 overflowing_support::handle_overflow(result, format_args!("{self} - {rhs}"))
389 }
390 (result, false) => Self(result),
391 }
392 }
393 }
394
395 impl SubAssign<Self> for Overflowing<$t> {
396 #[inline(always)]
397 fn sub_assign(&mut self, rhs: Self) {
398 *self = *self - rhs;
399 }
400 }
401
402 impl SubAssign<&Self> for Overflowing<$t> {
403 #[inline(always)]
404 fn sub_assign(&mut self, rhs: &Self) {
405 *self = *self - *rhs;
406 }
407 }
408
409 impl std::iter::Sum<Overflowing<$t>> for Overflowing<$t> {
410 #[inline(always)]
411 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
412 iter.fold(Self::ZERO, |a, b| a + b)
413 }
414 }
415
416 impl<'a> std::iter::Sum<&'a Overflowing<$t>> for Overflowing<$t> {
417 #[inline(always)]
418 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
419 iter.fold(Self::ZERO, |a, b| a + b)
420 }
421 }
422
423 impl Mul for Overflowing<$t> {
424 type Output = Self;
425
426 #[inline(always)]
427 fn mul(self, rhs: Self) -> Self::Output {
428 match self.0.overflowing_mul(rhs.0) {
429 (result, true) => {
430 overflowing_support::handle_overflow(result, format_args!("{self} * {rhs}"))
431 }
432 (result, false) => Self(result),
433 }
434 }
435 }
436
437 #[cfg(feature = "differential-dataflow")]
438 impl differential_dataflow::difference::IsZero for Overflowing<$t> {
439 #[inline(always)]
440 fn is_zero(&self) -> bool {
441 self.0.is_zero()
442 }
443 }
444
445 #[cfg(feature = "differential-dataflow")]
446 impl differential_dataflow::difference::Semigroup for Overflowing<$t> {
447 #[inline(always)]
448 fn plus_equals(&mut self, rhs: &Self) {
449 *self += *rhs
450 }
451 }
452
453 #[cfg(feature = "differential-dataflow")]
454 impl differential_dataflow::difference::Monoid for Overflowing<$t> {
455 #[inline(always)]
456 fn zero() -> Self {
457 Self::ZERO
458 }
459 }
460
461 #[cfg(feature = "differential-dataflow")]
462 impl differential_dataflow::difference::Multiply<Self> for Overflowing<$t> {
463 type Output = Self;
464 #[inline(always)]
465 fn multiply(self, rhs: &Self) -> Self::Output {
466 self * *rhs
467 }
468 }
469
470 #[cfg(feature = "columnation")]
471 impl columnation::Columnation for Overflowing<$t> {
472 type InnerRegion = columnation::CopyRegion<Self>;
473 }
474
475 impl std::str::FromStr for Overflowing<$t> {
476 type Err = <$t as std::str::FromStr>::Err;
477
478 #[inline(always)]
479 fn from_str(s: &str) -> Result<Self, Self::Err> {
480 <$t>::from_str(s).map(Self)
481 }
482 }
483
484 impl std::hash::Hash for Overflowing<$t> {
485 #[inline(always)]
486 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
487 self.0.hash(state);
488 }
489 }
490
491 impl<T> crate::cast::CastFrom<T> for Overflowing<$t>
492 where
493 $t: crate::cast::CastFrom<T>,
494 {
495 #[inline(always)]
496 fn cast_from(value: T) -> Self {
497 Self(<$t>::cast_from(value))
498 }
499 }
500
501 #[cfg(feature = "num-traits")]
502 impl num_traits::identities::Zero for Overflowing<$t> {
503 #[inline(always)]
504 fn zero() -> Self {
505 Self::ZERO
506 }
507 #[inline(always)]
508 fn is_zero(&self) -> bool {
509 self.0.is_zero()
510 }
511 }
512
513 #[cfg(feature = "num-traits")]
514 impl num_traits::identities::One for Overflowing<$t> {
515 #[inline(always)]
516 fn one() -> Self {
517 Self::ONE
518 }
519 }
520
521 #[cfg(feature = "num-traits")]
522 impl num_traits::Num for Overflowing<$t> {
523 type FromStrRadixErr = <$t as num_traits::Num>::FromStrRadixErr;
524
525 #[inline(always)]
526 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
527 <$t>::from_str_radix(str, radix).map(Self)
528 }
529 }
530 };
531}
532
533macro_rules! impl_overflowing_from {
534 ($t:ty, $($f:ty)+) => {
535 $(
536 impl From<$f> for Overflowing<$t> {
537 #[inline(always)]
538 fn from(value: $f) -> Self {
539 Self(value.into())
540 }
541 }
542 )+
543 };
544}
545
546macro_rules! impl_overflowing_from_overflowing {
547 ($t:ty, $($f:ty)+) => {
548 $(
549 impl From<Overflowing<$f>> for Overflowing<$t> {
550 #[inline(always)]
551 fn from(value: Overflowing<$f>) -> Self {
552 Self(value.0.into())
553 }
554 }
555 )+
556 };
557}
558
559macro_rules! impl_overflowing_try_from {
560 ($t:ty, $($f:ty)+) => {
561 $(
562 impl TryFrom<$f> for Overflowing<$t> {
563 type Error = <$t as TryFrom<$f>>::Error;
564 #[inline(always)]
565 fn try_from(value: $f) -> Result<Self, Self::Error> {
566 <$t>::try_from(value).map(Self)
567 }
568 }
569
570 impl TryFrom<Overflowing<$f>> for Overflowing<$t> {
571 type Error = <$t as TryFrom<$f>>::Error;
572 #[inline(always)]
573 fn try_from(value: Overflowing<$f>) -> Result<Self, Self::Error> {
574 <$t>::try_from(value.0).map(Self)
575 }
576 }
577 )+
578 };
579}
580
581macro_rules! impl_overflowing_signed {
583 ($t:ty, $u:ty) => {
584 impl Overflowing<$t> {
585 pub const MINUS_ONE: Self = Self(-1);
587
588 pub fn abs(self) -> Self {
590 Self(self.0.abs())
591 }
592
593 #[inline(always)]
595 pub fn unsigned_abs(self) -> $u {
596 self.0.unsigned_abs()
597 }
598
599 pub fn is_positive(self) -> bool {
610 self > Self::ZERO
611 }
612
613 pub fn is_negative(self) -> bool {
624 self < Self::ZERO
625 }
626 }
627
628 impl Neg for Overflowing<$t> {
629 type Output = Overflowing<<$t as Neg>::Output>;
630
631 #[inline(always)]
632 fn neg(self) -> Self::Output {
633 match self.0.overflowing_neg() {
634 (result, true) => {
635 overflowing_support::handle_overflow(result, format_args!("-{self}"))
636 }
637 (result, false) => Self(result),
638 }
639 }
640 }
641
642 impl Neg for &Overflowing<$t> {
643 type Output = Overflowing<<$t as Neg>::Output>;
644
645 #[inline(always)]
646 fn neg(self) -> Self::Output {
647 match self.0.overflowing_neg() {
648 (result, true) => {
649 overflowing_support::handle_overflow(result, format_args!("-{self}"))
650 }
651 (result, false) => Overflowing(result),
652 }
653 }
654 }
655
656 #[cfg(feature = "differential-dataflow")]
657 impl differential_dataflow::difference::Abelian for Overflowing<$t> {
658 #[inline(always)]
659 fn negate(&mut self) {
660 *self = -*self
661 }
662 }
663
664 #[cfg(feature = "num-traits")]
665 impl num_traits::sign::Signed for Overflowing<$t> {
666 #[inline(always)]
667 fn abs(&self) -> Self {
668 Self(self.0.abs())
669 }
670 #[inline(always)]
671 fn abs_sub(&self, other: &Self) -> Self {
672 Self(self.0.abs_sub(&other.0))
673 }
674 #[inline(always)]
675 fn signum(&self) -> Self {
676 Self(self.0.signum())
677 }
678 #[inline(always)]
679 fn is_positive(&self) -> bool {
680 self.0.is_positive()
681 }
682 #[inline(always)]
683 fn is_negative(&self) -> bool {
684 self.0.is_negative()
685 }
686 }
687 };
688}
689
690macro_rules! overflowing {
691 ($t:ty, $($fit:ty)+, $($may_fit:ty)+ $(, $unsigned:ty)?) => {
692 impl_overflowing!($t);
693 impl_overflowing_from!($t, $($fit)+ $t);
694 impl_overflowing_from_overflowing!($t, $($fit)+);
695 impl_overflowing_try_from!($t, $($may_fit)+);
696 $( impl_overflowing_signed!($t, $unsigned); )?
697 };
698}
699
700overflowing!(u8, bool, u16 u32 u64 u128 i8 i16 i32 i64 i128 isize usize);
702overflowing!(u16, bool u8, u32 u64 u128 i8 i16 i32 i64 i128 isize usize);
703overflowing!(u32, bool u8 u16, u64 u128 i8 i16 i32 i64 i128 isize usize);
704overflowing!(u64, bool u8 u16 u32, u128 i8 i16 i32 i64 i128 isize usize);
705overflowing!(u128, bool u8 u16 u32 u64, i8 i16 i32 i64 i128 isize usize);
706
707overflowing!(i8, bool, u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize, u8);
708overflowing!(i16, bool i8 u8, u16 i32 u32 i64 u64 i128 u128 isize usize, u16);
709overflowing!(i32, bool i8 u8 i16 u16, u32 i64 u64 i128 u128 isize usize, u32);
710overflowing!(i64, bool i8 u8 i16 u16 i32 u32, u64 i128 u128 isize usize, u64);
711overflowing!(i128, bool i8 u8 i16 u16 i32 u32 i64 u64, u128 isize usize, u128);
712
713mod overflowing_support {
714 use std::sync::atomic::AtomicUsize;
715
716 use crate::overflowing::OverflowingBehavior;
717
718 const MODE_IGNORE: usize = 0;
720 const MODE_SOFT_PANIC: usize = 1;
722 const MODE_PANIC: usize = 2;
724
725 static OVERFLOWING_MODE: AtomicUsize = AtomicUsize::new(MODE_IGNORE);
726
727 #[track_caller]
729 #[cold]
730 pub(super) fn handle_overflow<T: Into<O>, O>(result: T, description: std::fmt::Arguments) -> O {
731 let mode = OVERFLOWING_MODE.load(std::sync::atomic::Ordering::Relaxed);
732 match mode {
733 #[cfg(not(target_arch = "wasm32"))]
734 MODE_SOFT_PANIC => crate::soft_panic_or_log!("Overflow: {description}"),
735 #[cfg(target_arch = "wasm32")]
738 MODE_SOFT_PANIC => panic!("Overflow: {description}"),
739 MODE_PANIC => panic!("Overflow: {description}"),
740 _ => {}
742 }
743 result.into()
744 }
745
746 pub(crate) fn set_overflowing_mode(behavior: OverflowingBehavior) {
748 let value = match behavior {
749 OverflowingBehavior::Panic => MODE_PANIC,
750 OverflowingBehavior::SoftPanic => MODE_SOFT_PANIC,
751 OverflowingBehavior::Ignore => MODE_IGNORE,
752 };
753 OVERFLOWING_MODE.store(value, std::sync::atomic::Ordering::Relaxed);
754 }
755}
756
757#[cfg(test)]
758mod test {
759 use super::*;
760
761 #[cfg(debug_assertions)]
762 #[crate::test]
763 #[should_panic]
764 fn test_panicking_add() {
765 set_behavior(OverflowingBehavior::Panic);
766 let _ = Overflowing::<i8>::MAX + Overflowing::<i8>::ONE;
767 }
768
769 #[crate::test]
770 fn test_wrapping_add() {
771 let result = Overflowing::<i8>::MAX.wrapping_add(Overflowing::<i8>::ONE);
772 assert_eq!(result, Overflowing::<i8>::MIN);
773 }
774
775 #[crate::test]
776 fn test_checked_add() {
777 let result = Overflowing::<i8>::MAX.checked_add(Overflowing::<i8>::ONE);
778 assert_eq!(result, None);
779 }
780
781 #[cfg(feature = "columnar")]
782 #[crate::test]
783 fn test_columnar_i128_round_trip() {
784 use ::columnar::{AsBytes, Borrow, BorrowedOf, Columnar, FromBytes, Index, Len};
785
786 let values = [
787 Overflowing::<i128>::MIN,
788 Overflowing(-7),
789 Overflowing::<i128>::ZERO,
790 Overflowing::<i128>::ONE,
791 Overflowing::<i128>::MAX,
792 ];
793 let container = Overflowing::<i128>::as_columns(values.iter());
794 assert_eq!(container.len(), values.len());
795 let borrowed = container.borrow();
796 for (index, value) in values.iter().enumerate() {
797 assert_eq!(borrowed.get(index), *value);
798 }
799
800 let bytes: Vec<&[u8]> = borrowed.as_bytes().map(|(_align, bytes)| bytes).collect();
801 let decoded = BorrowedOf::<Overflowing<i128>>::from_bytes(&mut bytes.into_iter());
802 assert_eq!(decoded.len(), values.len());
803 for (index, value) in values.iter().enumerate() {
804 assert_eq!(decoded.get(index), *value);
805 }
806
807 let mut words = Vec::new();
810 ::columnar::bytes::indexed::encode(&mut words, &borrowed);
811 let store = ::columnar::bytes::indexed::DecodedStore::new(&words);
812 let decoded = BorrowedOf::<Overflowing<i128>>::from_store(&store, &mut 0);
813 assert_eq!(decoded.len(), values.len());
814 for (index, value) in values.iter().enumerate() {
815 assert_eq!(decoded.get(index), *value);
816 }
817 }
818}