Skip to main content

polars_arrow/array/binview/
mutable.rs

1use std::any::Any;
2use std::fmt::{Debug, Formatter};
3use std::ops::Deref;
4
5use hashbrown::hash_map::Entry;
6use polars_buffer::Buffer;
7use polars_error::PolarsResult;
8use polars_utils::aliases::{InitHashMaps, PlHashMap};
9
10use crate::array::binview::iterator::MutableBinaryViewValueIter;
11use crate::array::binview::view::validate_views_utf8_only;
12use crate::array::binview::{
13    BinaryViewArrayGeneric, DEFAULT_BLOCK_SIZE, MAX_EXP_BLOCK_SIZE, ViewType,
14};
15use crate::array::{Array, BINVIEW_ARROW_BUFFER_LEN_LIMIT, MutableArray, TryExtend, TryPush, View};
16use crate::bitmap::MutableBitmap;
17use crate::datatypes::ArrowDataType;
18use crate::legacy::trusted_len::TrustedLenPush;
19use crate::trusted_len::TrustedLen;
20
21// Invariants:
22//
23// - Each view must point to a valid slice of a buffer
24// - `total_buffer_len` must be equal to `completed_buffers.iter().map(Vec::len).sum()`
25// - `total_bytes_len` must be equal to `views.iter().map(View::len).sum()`
26pub struct MutableBinaryViewArray<T: ViewType + ?Sized> {
27    pub(crate) views: Vec<View>,
28    pub(crate) completed_buffers: Vec<Buffer<u8>>,
29    pub(crate) in_progress_buffer: Vec<u8>,
30    pub(crate) validity: Option<MutableBitmap>,
31    pub(crate) phantom: std::marker::PhantomData<T>,
32    /// Total bytes length if we would concatenate them all.
33    pub(crate) total_bytes_len: usize,
34    /// Total bytes in the buffer (excluding remaining capacity)
35    pub(crate) total_buffer_len: usize,
36    /// Mapping from `Buffer::deref()` to index in `completed_buffers`.
37    /// Used in `push_view()`.
38    pub(crate) stolen_buffers: PlHashMap<usize, u32>,
39}
40
41impl<T: ViewType + ?Sized> Clone for MutableBinaryViewArray<T> {
42    fn clone(&self) -> Self {
43        Self {
44            views: self.views.clone(),
45            completed_buffers: self.completed_buffers.clone(),
46            in_progress_buffer: self.in_progress_buffer.clone(),
47            validity: self.validity.clone(),
48            phantom: Default::default(),
49            total_bytes_len: self.total_bytes_len,
50            total_buffer_len: self.total_buffer_len,
51            stolen_buffers: PlHashMap::new(),
52        }
53    }
54}
55
56impl<T: ViewType + ?Sized> Debug for MutableBinaryViewArray<T> {
57    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58        write!(f, "mutable-binview{:?}", T::DATA_TYPE)
59    }
60}
61
62impl<T: ViewType + ?Sized> Default for MutableBinaryViewArray<T> {
63    fn default() -> Self {
64        Self::with_capacity(0)
65    }
66}
67
68impl<T: ViewType + ?Sized> From<MutableBinaryViewArray<T>> for BinaryViewArrayGeneric<T> {
69    fn from(mut value: MutableBinaryViewArray<T>) -> Self {
70        value.finish_in_progress();
71        unsafe {
72            Self::new_unchecked(
73                T::DATA_TYPE,
74                value.views.into(),
75                Buffer::from(value.completed_buffers),
76                value.validity.map(|b| b.into()),
77                Some(value.total_bytes_len),
78                value.total_buffer_len,
79            )
80        }
81    }
82}
83
84impl<T: ViewType + ?Sized> MutableBinaryViewArray<T> {
85    pub fn new() -> Self {
86        Self::default()
87    }
88
89    pub fn with_capacity(capacity: usize) -> Self {
90        Self {
91            views: Vec::with_capacity(capacity),
92            completed_buffers: vec![],
93            in_progress_buffer: vec![],
94            validity: None,
95            phantom: Default::default(),
96            total_buffer_len: 0,
97            total_bytes_len: 0,
98            stolen_buffers: PlHashMap::new(),
99        }
100    }
101
102    /// Get a mutable reference to the [`Vec`] of [`View`]s in this [`MutableBinaryViewArray`].
103    ///
104    /// # Safety
105    ///
106    /// This is safe as long as any mutation of the [`Vec`] does not break any invariants of the
107    /// [`MutableBinaryViewArray`] before it is read again.
108    #[inline]
109    pub unsafe fn views_mut(&mut self) -> &mut Vec<View> {
110        &mut self.views
111    }
112
113    /// Set the `total_bytes_len` of the [`MutableBinaryViewArray`]
114    ///
115    /// # Safety
116    ///
117    /// This should not break invariants of the [`MutableBinaryViewArray`]
118    #[inline]
119    pub unsafe fn set_total_bytes_len(&mut self, value: usize) {
120        #[cfg(debug_assertions)]
121        {
122            let actual_length: usize = self.views().iter().map(|v| v.length as usize).sum();
123            assert_eq!(value, actual_length);
124        }
125
126        self.total_bytes_len = value;
127    }
128
129    pub fn total_bytes_len(&self) -> usize {
130        self.total_bytes_len
131    }
132
133    pub fn total_buffer_len(&self) -> usize {
134        self.total_buffer_len
135    }
136
137    #[inline]
138    pub fn views(&self) -> &[View] {
139        &self.views
140    }
141
142    #[inline]
143    pub fn completed_buffers(&self) -> &[Buffer<u8>] {
144        &self.completed_buffers
145    }
146
147    pub fn validity(&mut self) -> Option<&mut MutableBitmap> {
148        self.validity.as_mut()
149    }
150
151    /// Reserves `additional` elements and `additional_buffer` on the buffer.
152    pub fn reserve(&mut self, additional: usize) {
153        self.views.reserve(additional);
154    }
155
156    #[inline]
157    pub fn len(&self) -> usize {
158        self.views.len()
159    }
160
161    #[inline]
162    pub fn capacity(&self) -> usize {
163        self.views.capacity()
164    }
165
166    fn init_validity(&mut self, unset_last: bool) {
167        let mut validity = MutableBitmap::with_capacity(self.views.capacity());
168        validity.extend_constant(self.len(), true);
169        if unset_last {
170            validity.set(self.len() - 1, false);
171        }
172        self.validity = Some(validity);
173    }
174
175    /// # Safety
176    /// - caller must allocate enough capacity
177    /// - caller must ensure the view and buffers match.
178    /// - The array must not have validity.
179    pub(crate) unsafe fn push_view_unchecked(&mut self, v: View, buffers: &[Buffer<u8>]) {
180        let len = v.length;
181        if len <= View::MAX_INLINE_SIZE {
182            debug_assert!(self.views.capacity() > self.views.len());
183            self.views.push_unchecked(v);
184            self.total_bytes_len += len as usize;
185        } else {
186            let data = buffers.get_unchecked(v.buffer_idx as usize);
187            let offset = v.offset as usize;
188            let bytes = data.get_unchecked(offset..offset + len as usize);
189            let t = T::from_bytes_unchecked(bytes);
190            self.push_value_ignore_validity(t)
191        }
192    }
193
194    /// # Safety
195    /// - caller must allocate enough capacity
196    /// - caller must ensure the view and buffers match.
197    /// - The array must not have validity.
198    /// - caller must not mix use this function with other push functions.
199    pub unsafe fn push_view_unchecked_dedupe(&mut self, mut v: View, buffers: &[Buffer<u8>]) {
200        let len = v.length;
201        self.total_bytes_len += len as usize;
202        if len <= View::MAX_INLINE_SIZE {
203            self.views.push_unchecked(v);
204        } else {
205            let buffer = buffers.get_unchecked(v.buffer_idx as usize);
206            let idx = match self.stolen_buffers.entry(buffer.deref().as_ptr() as usize) {
207                Entry::Occupied(entry) => *entry.get(),
208                Entry::Vacant(entry) => {
209                    let idx = self.completed_buffers.len() as u32;
210                    entry.insert(idx);
211                    self.completed_buffers.push(buffer.clone());
212                    self.total_buffer_len += buffer.len();
213                    idx
214                },
215            };
216            v.buffer_idx = idx;
217            self.views.push_unchecked(v);
218        }
219    }
220
221    pub fn push_view(&mut self, mut v: View, buffers: &[Buffer<u8>]) {
222        let len = v.length;
223        self.total_bytes_len += len as usize;
224        if len <= View::MAX_INLINE_SIZE {
225            self.views.push(v);
226        } else {
227            // Do no mix use of push_view and push_value_ignore_validity -
228            // it causes fragmentation.
229            self.finish_in_progress();
230
231            let buffer = &buffers[v.buffer_idx as usize];
232            let idx = match self.stolen_buffers.entry(buffer.deref().as_ptr() as usize) {
233                Entry::Occupied(entry) => {
234                    let idx = *entry.get();
235                    let target_buffer = &self.completed_buffers[idx as usize];
236                    debug_assert_eq!(buffer, target_buffer);
237                    idx
238                },
239                Entry::Vacant(entry) => {
240                    let idx = self.completed_buffers.len() as u32;
241                    entry.insert(idx);
242                    self.completed_buffers.push(buffer.clone());
243                    self.total_buffer_len += buffer.len();
244                    idx
245                },
246            };
247            v.buffer_idx = idx;
248            self.views.push(v);
249        }
250        if let Some(validity) = &mut self.validity {
251            validity.push(true)
252        }
253    }
254
255    #[inline]
256    pub fn push_value_ignore_validity<V: AsRef<T>>(&mut self, value: V) {
257        let bytes = value.as_ref().to_bytes();
258        self.total_bytes_len += bytes.len();
259        let view = self.push_value_into_buffer(bytes);
260        self.views.push(view);
261    }
262
263    #[inline]
264    pub fn push_buffer(&mut self, buffer: Buffer<u8>) -> u32 {
265        self.finish_in_progress();
266
267        let buffer_idx = self.completed_buffers.len();
268        self.total_buffer_len += buffer.len();
269        self.completed_buffers.push(buffer);
270        buffer_idx as u32
271    }
272
273    #[inline]
274    pub fn push_value<V: AsRef<T>>(&mut self, value: V) {
275        if let Some(validity) = &mut self.validity {
276            validity.push(true)
277        }
278        self.push_value_ignore_validity(value)
279    }
280
281    #[inline]
282    pub fn push<V: AsRef<T>>(&mut self, value: Option<V>) {
283        if let Some(value) = value {
284            self.push_value(value)
285        } else {
286            self.push_null()
287        }
288    }
289
290    #[inline]
291    pub fn push_null(&mut self) {
292        self.views.push(View::default());
293        match &mut self.validity {
294            Some(validity) => validity.push(false),
295            None => self.init_validity(true),
296        }
297    }
298
299    /// Get a [`View`] for a specific set of bytes.
300    pub fn push_value_into_buffer(&mut self, bytes: &[u8]) -> View {
301        assert!(bytes.len() <= u32::MAX as usize);
302
303        if bytes.len() <= View::MAX_INLINE_SIZE as usize {
304            View::new_inline(bytes)
305        } else {
306            self.total_buffer_len += bytes.len();
307
308            // We want to make sure that we never have to memcopy between buffers. So if the
309            // current buffer is not large enough, create a new buffer that is large enough and try
310            // to anticipate the larger size.
311            if self.in_progress_buffer.len().saturating_add(bytes.len())
312                > usize::min(
313                    BINVIEW_ARROW_BUFFER_LEN_LIMIT,
314                    self.in_progress_buffer.capacity(),
315                )
316            {
317                const {
318                    assert!(MAX_EXP_BLOCK_SIZE < BINVIEW_ARROW_BUFFER_LEN_LIMIT);
319                }
320
321                // Allocate a new buffer and flush the old buffer.
322                let new_capacity = usize::max(
323                    bytes.len(),
324                    (self.in_progress_buffer.capacity() * 2)
325                        .clamp(DEFAULT_BLOCK_SIZE, MAX_EXP_BLOCK_SIZE),
326                );
327
328                let in_progress = Vec::with_capacity(new_capacity);
329                let flushed = std::mem::replace(&mut self.in_progress_buffer, in_progress);
330                if !flushed.is_empty() {
331                    self.completed_buffers.push(flushed.into())
332                }
333            }
334
335            let offset = self.in_progress_buffer.len() as u32;
336            self.in_progress_buffer.extend_from_slice(bytes);
337
338            let buffer_idx = u32::try_from(self.completed_buffers.len()).unwrap();
339
340            View::new_from_bytes(bytes, buffer_idx, offset)
341        }
342    }
343
344    pub fn extend_null(&mut self, additional: usize) {
345        if self.validity.is_none() && additional > 0 {
346            self.init_validity(false);
347        }
348        self.views
349            .extend(std::iter::repeat_n(View::default(), additional));
350        if let Some(validity) = &mut self.validity {
351            validity.extend_constant(additional, false);
352        }
353    }
354
355    pub fn extend_constant<V: AsRef<T>>(&mut self, additional: usize, value: Option<V>) {
356        if value.is_none() && self.validity.is_none() {
357            self.init_validity(false);
358        }
359
360        if let Some(validity) = &mut self.validity {
361            validity.extend_constant(additional, value.is_some())
362        }
363
364        // Push and pop to get the properly encoded value.
365        // For long string this leads to a dictionary encoding,
366        // as we push the string only once in the buffers
367        if let Some(bytes) = value {
368            let view = self.push_value_into_buffer(bytes.as_ref().to_bytes());
369            self.views.extend(std::iter::repeat_n(view, additional));
370            self.total_bytes_len += view.length as usize * additional;
371        }
372    }
373
374    impl_mutable_array_mut_validity!();
375
376    #[inline]
377    pub fn extend_values<I, P>(&mut self, iterator: I)
378    where
379        I: Iterator<Item = P>,
380        P: AsRef<T>,
381    {
382        self.reserve(iterator.size_hint().0);
383        for v in iterator {
384            self.push_value(v)
385        }
386    }
387
388    #[inline]
389    pub fn extend_trusted_len_values<I, P>(&mut self, iterator: I)
390    where
391        I: TrustedLen<Item = P>,
392        P: AsRef<T>,
393    {
394        self.extend_values(iterator)
395    }
396
397    #[inline]
398    pub fn extend<I, P>(&mut self, iterator: I)
399    where
400        I: Iterator<Item = Option<P>>,
401        P: AsRef<T>,
402    {
403        self.reserve(iterator.size_hint().0);
404        for p in iterator {
405            self.push(p)
406        }
407    }
408
409    #[inline]
410    pub fn extend_trusted_len<I, P>(&mut self, iterator: I)
411    where
412        I: TrustedLen<Item = Option<P>>,
413        P: AsRef<T>,
414    {
415        self.extend(iterator)
416    }
417
418    #[inline]
419    pub fn extend_views<I>(&mut self, iterator: I, buffers: &[Buffer<u8>])
420    where
421        I: Iterator<Item = Option<View>>,
422    {
423        self.reserve(iterator.size_hint().0);
424        for p in iterator {
425            match p {
426                Some(v) => self.push_view(v, buffers),
427                None => self.push_null(),
428            }
429        }
430    }
431
432    #[inline]
433    pub fn extend_views_trusted_len<I>(&mut self, iterator: I, buffers: &[Buffer<u8>])
434    where
435        I: TrustedLen<Item = Option<View>>,
436    {
437        self.extend_views(iterator, buffers);
438    }
439
440    #[inline]
441    pub fn extend_non_null_views<I>(&mut self, iterator: I, buffers: &[Buffer<u8>])
442    where
443        I: Iterator<Item = View>,
444    {
445        self.reserve(iterator.size_hint().0);
446        for v in iterator {
447            self.push_view(v, buffers);
448        }
449    }
450
451    #[inline]
452    pub fn extend_non_null_views_trusted_len<I>(&mut self, iterator: I, buffers: &[Buffer<u8>])
453    where
454        I: TrustedLen<Item = View>,
455    {
456        self.extend_non_null_views(iterator, buffers);
457    }
458
459    /// # Safety
460    /// Same as `push_view_unchecked()`.
461    #[inline]
462    pub unsafe fn extend_non_null_views_unchecked<I>(&mut self, iterator: I, buffers: &[Buffer<u8>])
463    where
464        I: Iterator<Item = View>,
465    {
466        self.reserve(iterator.size_hint().0);
467        for v in iterator {
468            self.push_view_unchecked(v, buffers);
469        }
470    }
471
472    /// # Safety
473    /// Same as `push_view_unchecked()`.
474    #[inline]
475    pub unsafe fn extend_non_null_views_unchecked_dedupe<I>(
476        &mut self,
477        iterator: I,
478        buffers: &[Buffer<u8>],
479    ) where
480        I: Iterator<Item = View>,
481    {
482        self.reserve(iterator.size_hint().0);
483        for v in iterator {
484            self.push_view_unchecked_dedupe(v, buffers);
485        }
486    }
487
488    #[inline]
489    pub fn from_iterator<I, P>(iterator: I) -> Self
490    where
491        I: Iterator<Item = Option<P>>,
492        P: AsRef<T>,
493    {
494        let mut mutable = Self::with_capacity(iterator.size_hint().0);
495        mutable.extend(iterator);
496        mutable
497    }
498
499    pub fn from_values_iter<I, P>(iterator: I) -> Self
500    where
501        I: Iterator<Item = P>,
502        P: AsRef<T>,
503    {
504        let mut mutable = Self::with_capacity(iterator.size_hint().0);
505        mutable.extend_values(iterator);
506        mutable
507    }
508
509    pub fn from<S: AsRef<T>, P: AsRef<[Option<S>]>>(slice: P) -> Self {
510        Self::from_iterator(slice.as_ref().iter().map(|opt_v| opt_v.as_ref()))
511    }
512
513    pub fn finish_in_progress(&mut self) -> bool {
514        if !self.in_progress_buffer.is_empty() {
515            self.completed_buffers
516                .push(std::mem::take(&mut self.in_progress_buffer).into());
517            true
518        } else {
519            false
520        }
521    }
522
523    #[inline]
524    pub fn freeze(self) -> BinaryViewArrayGeneric<T> {
525        self.into()
526    }
527
528    #[inline]
529    pub fn freeze_with_dtype(self, dtype: ArrowDataType) -> BinaryViewArrayGeneric<T> {
530        let mut arr: BinaryViewArrayGeneric<T> = self.into();
531        arr.dtype = dtype;
532        arr
533    }
534
535    pub fn take(self) -> (Vec<View>, Vec<Buffer<u8>>) {
536        (self.views, self.completed_buffers)
537    }
538
539    #[inline]
540    pub fn value(&self, i: usize) -> &T {
541        assert!(i < self.len());
542        unsafe { self.value_unchecked(i) }
543    }
544
545    /// Returns the element at index `i`
546    ///
547    /// # Safety
548    /// Assumes that the `i < self.len`.
549    #[inline]
550    pub unsafe fn value_unchecked(&self, i: usize) -> &T {
551        self.value_from_view_unchecked(self.views.get_unchecked(i))
552    }
553
554    /// Returns the element indicated by the given view.
555    ///
556    /// # Safety
557    /// Assumes the View belongs to this MutableBinaryViewArray.
558    pub unsafe fn value_from_view_unchecked<'a>(&'a self, view: &'a View) -> &'a T {
559        // View layout:
560        // length: 4 bytes
561        // prefix: 4 bytes
562        // buffer_index: 4 bytes
563        // offset: 4 bytes
564
565        // Inlined layout:
566        // length: 4 bytes
567        // data: 12 bytes
568        let len = view.length;
569        let bytes = if len <= View::MAX_INLINE_SIZE {
570            let ptr = view as *const View as *const u8;
571            std::slice::from_raw_parts(ptr.add(4), len as usize)
572        } else {
573            let buffer_idx = view.buffer_idx as usize;
574            let offset = view.offset;
575
576            let data = if buffer_idx == self.completed_buffers.len() {
577                self.in_progress_buffer.as_slice()
578            } else {
579                self.completed_buffers.get_unchecked(buffer_idx)
580            };
581
582            let offset = offset as usize;
583            data.get_unchecked(offset..offset + len as usize)
584        };
585        T::from_bytes_unchecked(bytes)
586    }
587
588    /// Returns an iterator of `&[u8]` over every element of this array, ignoring the validity
589    pub fn values_iter(&self) -> MutableBinaryViewValueIter<'_, T> {
590        MutableBinaryViewValueIter::new(self)
591    }
592
593    pub fn extend_from_array(&mut self, other: &BinaryViewArrayGeneric<T>) {
594        let slf_len = self.len();
595        match (&mut self.validity, other.validity()) {
596            (None, None) => {},
597            (Some(v), None) => v.extend_constant(other.len(), true),
598            (v @ None, Some(other)) => {
599                let mut bm = MutableBitmap::with_capacity(slf_len + other.len());
600                bm.extend_constant(slf_len, true);
601                bm.extend_from_bitmap(other);
602                *v = Some(bm);
603            },
604            (Some(slf), Some(other)) => slf.extend_from_bitmap(other),
605        }
606
607        if other.total_buffer_len() == 0 {
608            self.views.extend(other.views().iter().copied());
609        } else {
610            self.finish_in_progress();
611
612            let buffer_offset = self.completed_buffers().len() as u32;
613            self.completed_buffers
614                .extend(other.data_buffers().iter().cloned());
615
616            self.views.extend(other.views().iter().map(|view| {
617                let mut view = *view;
618                if view.length > View::MAX_INLINE_SIZE {
619                    view.buffer_idx += buffer_offset;
620                }
621                view
622            }));
623
624            let new_total_buffer_len = self.total_buffer_len() + other.total_buffer_len();
625            self.total_buffer_len = new_total_buffer_len;
626        }
627
628        self.total_bytes_len = self.total_bytes_len() + other.total_bytes_len();
629    }
630}
631
632impl MutableBinaryViewArray<[u8]> {
633    pub fn validate_utf8(&mut self, buffer_offset: usize, views_offset: usize) -> PolarsResult<()> {
634        // Finish the in progress as it might be required for validation.
635        let pushed = self.finish_in_progress();
636        // views are correct
637        unsafe {
638            validate_views_utf8_only(
639                &self.views[views_offset..],
640                &self.completed_buffers,
641                buffer_offset,
642            )?
643        }
644        // Restore in-progress buffer as we don't want to get too small buffers
645        if pushed {
646            if let Some(last) = self.completed_buffers.pop() {
647                self.in_progress_buffer = last.into_mut().right().unwrap();
648            }
649        }
650        Ok(())
651    }
652}
653
654impl<T: ViewType + ?Sized, P: AsRef<T>> Extend<Option<P>> for MutableBinaryViewArray<T> {
655    #[inline]
656    fn extend<I: IntoIterator<Item = Option<P>>>(&mut self, iter: I) {
657        Self::extend(self, iter.into_iter())
658    }
659}
660
661impl<T: ViewType + ?Sized, P: AsRef<T>> FromIterator<Option<P>> for MutableBinaryViewArray<T> {
662    #[inline]
663    fn from_iter<I: IntoIterator<Item = Option<P>>>(iter: I) -> Self {
664        Self::from_iterator(iter.into_iter())
665    }
666}
667
668impl<T: ViewType + ?Sized> MutableArray for MutableBinaryViewArray<T> {
669    fn dtype(&self) -> &ArrowDataType {
670        T::dtype()
671    }
672
673    fn len(&self) -> usize {
674        MutableBinaryViewArray::len(self)
675    }
676
677    fn validity(&self) -> Option<&MutableBitmap> {
678        self.validity.as_ref()
679    }
680
681    fn as_box(&mut self) -> Box<dyn Array> {
682        let mutable = std::mem::take(self);
683        let arr: BinaryViewArrayGeneric<T> = mutable.into();
684        arr.boxed()
685    }
686
687    fn as_any(&self) -> &dyn Any {
688        self
689    }
690
691    fn as_mut_any(&mut self) -> &mut dyn Any {
692        self
693    }
694
695    fn push_null(&mut self) {
696        MutableBinaryViewArray::push_null(self)
697    }
698
699    fn reserve(&mut self, additional: usize) {
700        MutableBinaryViewArray::reserve(self, additional)
701    }
702
703    fn shrink_to_fit(&mut self) {
704        self.views.shrink_to_fit()
705    }
706}
707
708impl<T: ViewType + ?Sized, P: AsRef<T>> TryExtend<Option<P>> for MutableBinaryViewArray<T> {
709    /// This is infallible and is implemented for consistency with all other types
710    #[inline]
711    fn try_extend<I: IntoIterator<Item = Option<P>>>(&mut self, iter: I) -> PolarsResult<()> {
712        self.extend(iter.into_iter());
713        Ok(())
714    }
715}
716
717impl<T: ViewType + ?Sized, P: AsRef<T>> TryPush<Option<P>> for MutableBinaryViewArray<T> {
718    /// This is infallible and is implemented for consistency with all other types
719    #[inline(always)]
720    fn try_push(&mut self, item: Option<P>) -> PolarsResult<()> {
721        self.push(item.as_ref().map(|p| p.as_ref()));
722        Ok(())
723    }
724}