vortex_vector/decimal/
generic_mut.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Definition and implementation of [`DVectorMut<D>`].
5
6use vortex_buffer::BufferMut;
7use vortex_dtype::NativeDecimalType;
8use vortex_dtype::PrecisionScale;
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_bail;
12use vortex_mask::MaskMut;
13
14use crate::VectorMutOps;
15use crate::VectorOps;
16use crate::decimal::DScalar;
17use crate::decimal::DVector;
18
19/// A mutable vector of decimal values with fixed precision and scale.
20///
21/// `D` is bound by [`NativeDecimalType`], which can be one of the native integer types (`i8`,
22/// `i16`, `i32`, `i64`, `i128`) or `i256`. `D` is used to store the decimal values.
23///
24/// The decimal vector maintains a [`PrecisionScale<D>`] that defines the precision (total number of
25/// digits) and scale (digits after the decimal point) for all values in the vector.
26///
27/// Unlike primitive vectors, decimal vectors require validation during construction and
28/// modification to ensure values stay within the bounds defined by their precision and scale.
29/// This makes operations like "push" fallible, thus we have a [`try_push()`] method instead.
30///
31/// [`try_push()`]: Self::try_push
32#[derive(Debug, Clone)]
33pub struct DVectorMut<D> {
34    /// The precision and scale of each decimal in the decimal vector.
35    pub(super) ps: PrecisionScale<D>,
36    /// The mutable buffer representing the vector decimal elements.
37    pub(super) elements: BufferMut<D>,
38    /// The validity mask (where `true` represents an element is **not** null).
39    pub(super) validity: MaskMut,
40}
41
42impl<D: NativeDecimalType> DVectorMut<D> {
43    /// Creates a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer, and
44    /// validity mask.
45    ///
46    /// # Panics
47    ///
48    /// Panics if:
49    ///
50    /// - The lengths of the `elements` and `validity` do not match.
51    /// - Any of the elements are out of bounds for the given [`PrecisionScale`].
52    pub fn new(ps: PrecisionScale<D>, elements: BufferMut<D>, validity: MaskMut) -> Self {
53        Self::try_new(ps, elements, validity).vortex_expect("Failed to create `DVector`")
54    }
55
56    /// Tries to create a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer,
57    /// and validity mask.
58    ///
59    /// # Errors
60    ///
61    /// Returns an error if:
62    ///
63    /// - The lengths of the `elements` and `validity` do not match.
64    /// - Any of the elements are out of bounds for the given [`PrecisionScale`].
65    pub fn try_new(
66        ps: PrecisionScale<D>,
67        elements: BufferMut<D>,
68        validity: MaskMut,
69    ) -> VortexResult<Self> {
70        if elements.len() != validity.len() {
71            vortex_bail!(
72                "Elements length {} does not match validity length {}",
73                elements.len(),
74                validity.len()
75            );
76        }
77
78        // We assert that each element is within bounds for the given precision/scale.
79        if !elements.iter().all(|e| ps.is_valid(*e)) {
80            vortex_bail!(
81                "One or more elements are out of bounds for precision {} and scale {}",
82                ps.precision(),
83                ps.scale()
84            );
85        }
86
87        Ok(Self {
88            ps,
89            elements,
90            validity,
91        })
92    }
93
94    /// Creates a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer, and
95    /// validity mask, _without_ validation.
96    ///
97    /// # Safety
98    ///
99    /// The caller must ensure:
100    ///
101    /// - The lengths of the elements and validity are equal.
102    /// - All elements are in bounds for the given [`PrecisionScale`].
103    pub unsafe fn new_unchecked(
104        ps: PrecisionScale<D>,
105        elements: BufferMut<D>,
106        validity: MaskMut,
107    ) -> Self {
108        if cfg!(debug_assertions) {
109            Self::try_new(ps, elements, validity).vortex_expect("Failed to create `DVectorMut`")
110        } else {
111            Self {
112                ps,
113                elements,
114                validity,
115            }
116        }
117    }
118
119    /// Create a new mutable primitive vector with the given capacity.
120    pub fn with_capacity(ps: PrecisionScale<D>, capacity: usize) -> Self {
121        Self {
122            ps,
123            elements: BufferMut::with_capacity(capacity),
124            validity: MaskMut::with_capacity(capacity),
125        }
126    }
127
128    /// Decomposes the decimal vector into its constituent parts ([`PrecisionScale`], decimal
129    /// buffer, and validity).
130    pub fn into_parts(self) -> (PrecisionScale<D>, BufferMut<D>, MaskMut) {
131        (self.ps, self.elements, self.validity)
132    }
133
134    /// Get the precision/scale of the decimal vector.
135    pub fn precision_scale(&self) -> PrecisionScale<D> {
136        self.ps
137    }
138
139    /// Returns a reference to the underlying elements buffer containing the decimal data.
140    pub fn elements(&self) -> &BufferMut<D> {
141        &self.elements
142    }
143
144    /// Returns a mutable reference to the underlying elements buffer containing the decimal data.
145    ///
146    /// # Safety
147    ///
148    /// Modifying the elements buffer directly may violate the precision/scale constraints.
149    /// The caller must ensure that any modifications maintain these invariants.
150    pub unsafe fn elements_mut(&mut self) -> &mut BufferMut<D> {
151        &mut self.elements
152    }
153
154    /// Returns a mutable reference to the underlying validity mask of the vector.
155    ///
156    /// # Safety
157    ///
158    /// The caller must ensure that when the length of the validity changes, the length
159    /// of the elements is changed to match it.
160    pub unsafe fn validity_mut(&mut self) -> &mut MaskMut {
161        &mut self.validity
162    }
163
164    /// Gets a nullable element at the given index, panicking on out-of-bounds.
165    ///
166    /// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
167    /// where `x: D`.
168    ///
169    /// Note that this `get` method is different from the standard library [`slice::get`], which
170    /// returns `None` if the index is out of bounds. This method will panic if the index is out of
171    /// bounds, and return `None` if the elements is null.
172    ///
173    /// # Panics
174    ///
175    /// Panics if the index is out of bounds.
176    pub fn get(&self, index: usize) -> Option<&D> {
177        self.validity.value(index).then(|| &self.elements[index])
178    }
179
180    /// Appends a new element to the end of the vector.
181    ///
182    /// # Errors
183    ///
184    /// Returns an error if the value is out of bounds for the vector's precision/scale.
185    pub fn try_push(&mut self, value: D) -> VortexResult<()> {
186        self.try_append_n(value, 1)
187    }
188
189    /// Appends n elements to the vector, all set to the given value.
190    ///
191    /// # Errors
192    ///
193    /// Returns an error if the value is out of bounds for the vector's precision/scale.
194    pub fn try_append_n(&mut self, value: D, n: usize) -> VortexResult<()> {
195        if !self.ps.is_valid(value) {
196            vortex_bail!("Value {:?} is out of bounds for {}", value, self.ps);
197        }
198
199        self.elements.push_n(value, n);
200        self.validity.append_n(true, n);
201        Ok(())
202    }
203}
204
205impl<D: NativeDecimalType> AsRef<[D]> for DVectorMut<D> {
206    fn as_ref(&self) -> &[D] {
207        &self.elements
208    }
209}
210
211impl<D: NativeDecimalType> VectorMutOps for DVectorMut<D> {
212    type Immutable = DVector<D>;
213
214    fn len(&self) -> usize {
215        self.elements.len()
216    }
217
218    fn validity(&self) -> &MaskMut {
219        &self.validity
220    }
221
222    fn capacity(&self) -> usize {
223        self.elements.capacity()
224    }
225
226    fn reserve(&mut self, additional: usize) {
227        self.elements.reserve(additional);
228        self.validity.reserve(additional);
229    }
230
231    fn clear(&mut self) {
232        self.elements.clear();
233        self.validity.clear();
234    }
235
236    fn truncate(&mut self, len: usize) {
237        self.elements.truncate(len);
238        self.validity.truncate(len);
239    }
240
241    fn extend_from_vector(&mut self, other: &DVector<D>) {
242        self.elements.extend_from_slice(&other.elements);
243        self.validity.append_mask(other.validity());
244    }
245
246    fn append_nulls(&mut self, n: usize) {
247        self.elements.extend((0..n).map(|_| D::default()));
248        self.validity.append_n(false, n);
249    }
250
251    fn append_zeros(&mut self, n: usize) {
252        self.elements.extend((0..n).map(|_| D::default()));
253        self.validity.append_n(true, n);
254    }
255
256    fn append_scalars(&mut self, scalar: &DScalar<D>, n: usize) {
257        match scalar.value() {
258            None => self.append_nulls(n),
259            Some(value) => self.try_append_n(value, n).vortex_expect("known to fit"),
260        }
261    }
262
263    fn freeze(self) -> DVector<D> {
264        DVector {
265            ps: self.ps,
266            elements: self.elements.freeze(),
267            validity: self.validity.freeze(),
268        }
269    }
270
271    fn split_off(&mut self, at: usize) -> Self {
272        DVectorMut {
273            ps: self.ps,
274            elements: self.elements.split_off(at),
275            validity: self.validity.split_off(at),
276        }
277    }
278
279    fn unsplit(&mut self, other: Self) {
280        if self.is_empty() {
281            *self = other;
282            return;
283        }
284        self.elements.unsplit(other.elements);
285        self.validity.unsplit(other.validity);
286    }
287}
288
289#[cfg(test)]
290mod tests {
291    use super::*;
292
293    #[test]
294    fn test_construction_and_validation() {
295        // Test with_capacity for different decimal types.
296        let ps_i32 = PrecisionScale::<i32>::new(9, 2);
297        let vec_i32 = DVectorMut::<i32>::with_capacity(ps_i32, 10);
298        assert_eq!(vec_i32.len(), 0);
299        assert!(vec_i32.capacity() >= 10);
300
301        let ps_i64 = PrecisionScale::<i64>::new(18, 4);
302        let vec_i64 = DVectorMut::<i64>::with_capacity(ps_i64, 5);
303        assert_eq!(vec_i64.len(), 0);
304        assert!(vec_i64.capacity() >= 5);
305
306        let ps_i128 = PrecisionScale::<i128>::new(38, 10);
307        let vec_i128 = DVectorMut::<i128>::with_capacity(ps_i128, 3);
308        assert_eq!(vec_i128.len(), 0);
309        assert!(vec_i128.capacity() >= 3);
310
311        // Test try_new with valid data.
312        let ps = ps_i32;
313        let elements = BufferMut::from_iter([100_i32, 200, 300]);
314        let validity = MaskMut::new_true(3);
315        let vec = DVectorMut::try_new(ps, elements, validity).unwrap();
316        assert_eq!(vec.len(), 3);
317        assert_eq!(vec.precision_scale().precision(), 9);
318        assert_eq!(vec.precision_scale().scale(), 2);
319
320        // Test try_new error handling - length mismatch.
321        let elements_bad = BufferMut::from_iter([100_i32, 200]);
322        let validity_bad = MaskMut::new_true(3);
323        let result = DVectorMut::try_new(ps, elements_bad, validity_bad);
324        assert!(result.is_err());
325
326        // Test try_new error handling - out of bounds values.
327        let too_large = 10_i32.pow(9); // 10^9 exceeds precision 9.
328        let elements_oob = BufferMut::from_iter([100_i32, too_large, 300]);
329        let validity_oob = MaskMut::new_true(3);
330        let result = DVectorMut::try_new(ps, elements_oob, validity_oob);
331        assert!(result.is_err());
332
333        // Test new_unchecked.
334        let elements_unchecked = BufferMut::from_iter([100_i32, 200]);
335        let validity_unchecked = MaskMut::new_true(2);
336        let vec_unchecked =
337            unsafe { DVectorMut::new_unchecked(ps, elements_unchecked, validity_unchecked) };
338        assert_eq!(vec_unchecked.len(), 2);
339    }
340
341    #[test]
342    fn test_push_append_and_access() {
343        let ps = PrecisionScale::<i32>::new(9, 2);
344        let mut vec = DVectorMut::<i32>::with_capacity(ps, 10);
345
346        // Test try_push with valid values.
347        vec.try_push(12345).unwrap(); // 123.45.
348        vec.try_push(9999).unwrap(); // 99.99.
349        vec.try_push(-5000).unwrap(); // -50.00.
350        assert_eq!(vec.len(), 3);
351
352        // Test try_push with out-of-bounds values.
353        let too_large = 10_i32.pow(9);
354        assert!(vec.try_push(too_large).is_err());
355        assert_eq!(vec.len(), 3); // Length unchanged after failed push.
356
357        // Test get without nulls.
358        assert_eq!(vec.get(0), Some(&12345));
359        assert_eq!(vec.get(1), Some(&9999));
360        assert_eq!(vec.get(2), Some(&-5000));
361
362        // Test append_nulls.
363        vec.append_nulls(2);
364        assert_eq!(vec.len(), 5);
365        assert_eq!(vec.get(3), None);
366        assert_eq!(vec.get(4), None);
367
368        // Test AsRef<[D]> slice access.
369        let slice = vec.as_ref();
370        assert_eq!(slice.len(), 5);
371        assert_eq!(slice[0], 12345);
372        assert_eq!(slice[1], 9999);
373        assert_eq!(slice[2], -5000);
374        // Note: slice[3] and slice[4] are default values (0) but marked as null in validity.
375    }
376
377    #[test]
378    fn test_vector_mut_ops_comprehensive() {
379        let ps = PrecisionScale::<i64>::new(10, 3);
380        let mut vec1 = DVectorMut::<i64>::with_capacity(ps, 10);
381        vec1.try_push(1000000).unwrap(); // 1000.000.
382        vec1.try_push(2000000).unwrap(); // 2000.000.
383        vec1.try_push(3000000).unwrap(); // 3000.000.
384        vec1.try_push(4000000).unwrap(); // 4000.000.
385
386        // Test extend_from_vector.
387        let mut vec2 = DVectorMut::<i64>::with_capacity(ps, 10);
388        vec2.try_push(5000000).unwrap(); // 5000.000.
389        vec2.try_push(6000000).unwrap(); // 6000.000.
390        let frozen_vec2 = vec2.freeze();
391
392        let original_len = vec1.len();
393        vec1.extend_from_vector(&frozen_vec2);
394        assert_eq!(vec1.len(), original_len + frozen_vec2.len());
395        assert_eq!(vec1.get(4), Some(&5000000));
396        assert_eq!(vec1.get(5), Some(&6000000));
397
398        // Test split_off and validity preservation.
399        vec1.append_nulls(2); // Add nulls at positions 6 and 7.
400        assert_eq!(vec1.len(), 8);
401
402        let split = vec1.split_off(5);
403        assert_eq!(vec1.len(), 5);
404        assert_eq!(split.len(), 3);
405
406        // Check that split preserved validity.
407        assert_eq!(split.get(0), Some(&6000000)); // Was at index 5.
408        assert_eq!(split.get(1), None); // Was null at index 6.
409        assert_eq!(split.get(2), None); // Was null at index 7.
410
411        // Test reserve and capacity management.
412        let initial_capacity = vec1.capacity();
413        vec1.reserve(20);
414        assert!(vec1.capacity() >= initial_capacity + 20);
415
416        // Test len() and capacity() tracking.
417        assert_eq!(vec1.len(), 5);
418        assert!(vec1.capacity() >= 25);
419
420        // Test unsplit - rejoin the vectors.
421        vec1.unsplit(split);
422        assert_eq!(vec1.len(), 8);
423        assert_eq!(vec1.get(6), None); // Verify null is still null after unsplit.
424        assert_eq!(vec1.get(7), None); // Verify null is still null after unsplit.
425    }
426
427    #[test]
428    fn test_freeze_and_immutable_vector() {
429        let ps = PrecisionScale::<i64>::new(15, 5);
430        let mut vec_mut = DVectorMut::<i64>::with_capacity(ps, 5);
431
432        // Add some values and nulls.
433        vec_mut.try_push(1234567890).unwrap(); // 12345.67890.
434        vec_mut.try_push(9876543210).unwrap(); // 98765.43210.
435        vec_mut.append_nulls(1);
436        vec_mut.try_push(5555555555).unwrap(); // 55555.55555.
437        vec_mut.append_nulls(1);
438
439        // Test freeze() to convert DVectorMut to DVector.
440        let vec_immutable = vec_mut.freeze();
441        assert_eq!(vec_immutable.len(), 5);
442
443        // Test DVector::get() with nulls.
444        assert_eq!(vec_immutable.get(0), Some(&1234567890));
445        assert_eq!(vec_immutable.get(1), Some(&9876543210));
446        assert_eq!(vec_immutable.get(2), None); // Null.
447        assert_eq!(vec_immutable.get(3), Some(&5555555555));
448        assert_eq!(vec_immutable.get(4), None); // Null.
449
450        // Test DVector::as_slice() through AsRef.
451        let slice = vec_immutable.as_ref();
452        assert_eq!(slice.len(), 5);
453        assert_eq!(slice[0], 1234567890);
454        assert_eq!(slice[3], 5555555555);
455
456        // Test precision_scale() getter on immutable vector.
457        assert_eq!(vec_immutable.precision_scale().precision(), 15);
458        assert_eq!(vec_immutable.precision_scale().scale(), 5);
459
460        // Test round-trip: DVector → DVectorMut (using try_into_mut).
461        let mut vec_mut_again = match vec_immutable.try_into_mut() {
462            Ok(v) => v,
463            Err(_) => {
464                // If conversion fails (buffer is shared), create a new mutable vector.
465                // This is expected in some cases when the buffer cannot be made mutable.
466                let ps = PrecisionScale::<i64>::new(15, 5);
467                let mut new_vec = DVectorMut::<i64>::with_capacity(ps, 6);
468                new_vec.try_push(1234567890).unwrap();
469                new_vec.try_push(9876543210).unwrap();
470                new_vec.append_nulls(1);
471                new_vec.try_push(5555555555).unwrap();
472                new_vec.append_nulls(1);
473                new_vec
474            }
475        };
476
477        assert_eq!(vec_mut_again.len(), 5);
478        vec_mut_again.try_push(7777777777).unwrap(); // 77777.77777.
479        assert_eq!(vec_mut_again.len(), 6);
480
481        // Freeze again and verify.
482        let vec_final = vec_mut_again.freeze();
483        assert_eq!(vec_final.len(), 6);
484        assert_eq!(vec_final.get(5), Some(&7777777777));
485    }
486
487    #[test]
488    fn test_precision_scale_combinations() {
489        // Test Decimal(9, 2) - common currency format.
490        let ps_9_2 = PrecisionScale::<i32>::new(9, 2);
491        let mut vec_9_2 = DVectorMut::<i32>::with_capacity(ps_9_2, 5);
492        vec_9_2.try_push(999999999).unwrap(); // Max: 9999999.99 stored as 999999999.
493        assert!(vec_9_2.try_push(1000000000).is_err()); // 10000000.00 stored as 1000000000 exceeds precision.
494        assert!(vec_9_2.try_push(-999999999).is_ok()); // Negative within bounds.
495        assert_eq!(vec_9_2.len(), 2);
496
497        // Test Decimal(38, 10) - high precision scientific.
498        let ps_38_10 = PrecisionScale::<i128>::new(38, 10);
499        let mut vec_38_10 = DVectorMut::<i128>::with_capacity(ps_38_10, 3);
500        let large_value = 10_i128.pow(28) - 1; // 10^28 - 1, well within 38 digits.
501        vec_38_10.try_push(large_value).unwrap();
502        assert_eq!(vec_38_10.len(), 1);
503
504        // Test Decimal(4, 0) - integer-only decimals that fit in i16.
505        let ps_4_0 = PrecisionScale::<i16>::new(4, 0);
506        let mut vec_4_0 = DVectorMut::<i16>::with_capacity(ps_4_0, 5);
507        vec_4_0.try_push(9999).unwrap(); // Max: 9999.
508        assert!(vec_4_0.try_push(10000).is_err()); // Exceeds 4 digits.
509        vec_4_0.try_push(-9999).unwrap(); // Negative within bounds.
510        assert_eq!(vec_4_0.len(), 2);
511
512        // Test with different underlying types.
513        // i8 with small precision/scale (max precision for i8 is 2).
514        let ps_2_1 = PrecisionScale::<i8>::new(2, 1);
515        let mut vec_i8 = DVectorMut::<i8>::with_capacity(ps_2_1, 3);
516        vec_i8.try_push(99).unwrap(); // 9.9.
517        assert!(vec_i8.try_push(100).is_err()); // 10.0 exceeds precision.
518
519        // i16 with moderate precision/scale (max precision for i16 is 4).
520        let ps_4_2 = PrecisionScale::<i16>::new(4, 2);
521        let mut vec_i16 = DVectorMut::<i16>::with_capacity(ps_4_2, 3);
522        vec_i16.try_push(999).unwrap(); // 9.99.
523        vec_i16.try_push(9999).unwrap(); // 99.99.
524        assert_eq!(vec_i16.len(), 2);
525    }
526
527    #[test]
528    fn test_empty_and_edge_cases() {
529        let ps = PrecisionScale::<i32>::new(9, 2);
530
531        // Test empty vector creation and operations.
532        let empty_vec = DVectorMut::<i32>::with_capacity(ps, 0);
533        assert_eq!(empty_vec.len(), 0);
534        // Capacity might be rounded up from the requested value.
535        let _ = empty_vec.capacity(); // Just verify it doesn't panic.
536
537        // Freeze empty vector.
538        let frozen_empty = empty_vec.freeze();
539        assert_eq!(frozen_empty.len(), 0);
540
541        // Test single element vector.
542        let mut single = DVectorMut::<i32>::with_capacity(ps, 1);
543        single.try_push(42).unwrap();
544        assert_eq!(single.len(), 1);
545        assert_eq!(single.get(0), Some(&42));
546
547        // Split single element vector at index 1.
548        // Original keeps [0, 1) = the element, split gets [1, len) = nothing.
549        let split_single = single.split_off(1);
550        assert_eq!(single.len(), 1); // Original keeps the element.
551        assert_eq!(split_single.len(), 0); // Split gets nothing.
552
553        // Test all-null vector.
554        let mut all_nulls = DVectorMut::<i32>::with_capacity(ps, 5);
555        all_nulls.append_nulls(5);
556        assert_eq!(all_nulls.len(), 5);
557        for i in 0..5 {
558            assert_eq!(all_nulls.get(i), None);
559        }
560
561        // Freeze all-null vector and check immutable.
562        let frozen_nulls = all_nulls.freeze();
563        assert_eq!(frozen_nulls.len(), 5);
564        for i in 0..5 {
565            assert_eq!(frozen_nulls.get(i), None);
566        }
567
568        // Test maximum capacity scenario - create large vector.
569        let mut large = DVectorMut::<i32>::with_capacity(ps, 1000);
570        for _ in 0..1000 {
571            large.try_push(999).unwrap();
572        }
573        assert_eq!(large.len(), 1000);
574        assert!(large.capacity() >= 1000);
575    }
576
577    #[test]
578    fn test_nulls_with_validity_mask() {
579        let ps = PrecisionScale::<i32>::new(8, 3);
580
581        // Create vector with specific null pattern using validity mask.
582        let elements = BufferMut::from_iter([1000_i32, 0, 2000, 0, 3000]); // 0s will be null.
583        let mut validity = MaskMut::with_capacity(5);
584        validity.append_n(true, 1); // index 0: valid
585        validity.append_n(false, 1); // index 1: null
586        validity.append_n(true, 1); // index 2: valid
587        validity.append_n(false, 1); // index 3: null
588        validity.append_n(true, 1); // index 4: valid
589        let mut vec = DVectorMut::new(ps, elements, validity);
590
591        assert_eq!(vec.len(), 5);
592        assert_eq!(vec.get(0), Some(&1000)); // 1.000.
593        assert_eq!(vec.get(1), None); // Null.
594        assert_eq!(vec.get(2), Some(&2000)); // 2.000.
595        assert_eq!(vec.get(3), None); // Null.
596        assert_eq!(vec.get(4), Some(&3000)); // 3.000.
597
598        // Extend with more values and nulls.
599        vec.try_push(4000).unwrap();
600        vec.append_nulls(2);
601        assert_eq!(vec.len(), 8);
602        assert_eq!(vec.get(5), Some(&4000));
603        assert_eq!(vec.get(6), None);
604        assert_eq!(vec.get(7), None);
605
606        // Split and verify nulls are preserved.
607        let split = vec.split_off(4);
608        assert_eq!(vec.len(), 4);
609        assert_eq!(split.len(), 4);
610
611        // Original vec should have: valid, null, valid, null.
612        assert_eq!(vec.get(1), None);
613        assert_eq!(vec.get(3), None);
614
615        // Split should have: valid, valid, null, null.
616        assert_eq!(split.get(0), Some(&3000));
617        assert_eq!(split.get(1), Some(&4000));
618        assert_eq!(split.get(2), None);
619        assert_eq!(split.get(3), None);
620    }
621}