polars_core/chunked_array/builder/list/
primitive.rs

1use super::*;
2
3pub struct ListPrimitiveChunkedBuilder<T>
4where
5    T: PolarsNumericType,
6{
7    pub builder: LargePrimitiveBuilder<T::Native>,
8    field: Field,
9    fast_explode: bool,
10}
11
12impl<T> ListPrimitiveChunkedBuilder<T>
13where
14    T: PolarsNumericType,
15{
16    pub fn new(
17        name: PlSmallStr,
18        capacity: usize,
19        values_capacity: usize,
20        inner_type: DataType,
21    ) -> Self {
22        debug_assert!(
23            inner_type.to_physical().is_primitive_numeric(),
24            "inner type must be primitive, got {inner_type}"
25        );
26        let values = MutablePrimitiveArray::<T::Native>::with_capacity(values_capacity);
27        let builder = LargePrimitiveBuilder::<T::Native>::new_with_capacity(values, capacity);
28        let field = Field::new(name, DataType::List(Box::new(inner_type)));
29
30        Self {
31            builder,
32            field,
33            fast_explode: true,
34        }
35    }
36
37    pub fn new_with_values_type(
38        name: PlSmallStr,
39        capacity: usize,
40        values_capacity: usize,
41        values_type: DataType,
42        logical_type: DataType,
43    ) -> Self {
44        let values = MutablePrimitiveArray::<T::Native>::with_capacity_from(
45            values_capacity,
46            values_type.to_arrow(CompatLevel::newest()),
47        );
48        let builder = LargePrimitiveBuilder::<T::Native>::new_with_capacity(values, capacity);
49        let field = Field::new(name, DataType::List(Box::new(logical_type)));
50        Self {
51            builder,
52            field,
53            fast_explode: true,
54        }
55    }
56
57    #[inline]
58    pub fn append_slice(&mut self, items: &[T::Native]) {
59        let values = self.builder.mut_values();
60        values.extend_from_slice(items);
61        self.builder.try_push_valid().unwrap();
62
63        if items.is_empty() {
64            self.fast_explode = false;
65        }
66    }
67
68    #[inline]
69    pub fn append_opt_slice(&mut self, opt_v: Option<&[T::Native]>) {
70        match opt_v {
71            Some(items) => self.append_slice(items),
72            None => {
73                self.builder.push_null();
74            },
75        }
76    }
77    /// Appends from an iterator over values
78    #[inline]
79    pub fn append_values_iter_trusted_len<I: Iterator<Item = T::Native> + TrustedLen>(
80        &mut self,
81        iter: I,
82    ) {
83        let values = self.builder.mut_values();
84
85        if iter.size_hint().0 == 0 {
86            self.fast_explode = false;
87        }
88        // SAFETY:
89        // trusted len, trust the type system
90        values.extend_values(iter);
91        self.builder.try_push_valid().unwrap();
92    }
93
94    #[inline]
95    pub fn append_values_iter<I: Iterator<Item = T::Native>>(&mut self, iter: I) {
96        let values = self.builder.mut_values();
97
98        if iter.size_hint().0 == 0 {
99            self.fast_explode = false;
100        }
101        values.extend_values(iter);
102        self.builder.try_push_valid().unwrap();
103    }
104
105    /// Appends from an iterator over values
106    #[inline]
107    pub fn append_iter<I: Iterator<Item = Option<T::Native>> + TrustedLen>(&mut self, iter: I) {
108        let values = self.builder.mut_values();
109
110        if iter.size_hint().0 == 0 {
111            self.fast_explode = false;
112        }
113        // SAFETY:
114        // trusted len, trust the type system
115        unsafe { values.extend_trusted_len_unchecked(iter) };
116        self.builder.try_push_valid().unwrap();
117    }
118}
119
120impl<T> ListBuilderTrait for ListPrimitiveChunkedBuilder<T>
121where
122    T: PolarsNumericType,
123{
124    #[inline]
125    fn append_null(&mut self) {
126        self.fast_explode = false;
127        self.builder.push_null();
128    }
129
130    #[inline]
131    fn append_series(&mut self, s: &Series) -> PolarsResult<()> {
132        if s.is_empty() {
133            self.fast_explode = false;
134        }
135        let physical = s.to_physical_repr();
136        let ca = physical.unpack::<T>().map_err(|_| {
137            polars_err!(SchemaMismatch: "cannot build list with different dtypes 
138
139Expected {}, got {}.", self.field.dtype(), s.dtype())
140        })?;
141        let values = self.builder.mut_values();
142
143        ca.downcast_iter().for_each(|arr| {
144            if arr.null_count() == 0 {
145                values.extend_from_slice(arr.values().as_slice())
146            } else {
147                // SAFETY:
148                // Arrow arrays are trusted length iterators.
149                unsafe { values.extend_trusted_len_unchecked(arr.into_iter()) }
150            }
151        });
152        // overflow of i64 is far beyond polars capable lengths.
153        unsafe { self.builder.try_push_valid().unwrap_unchecked() };
154        Ok(())
155    }
156
157    fn field(&self) -> &Field {
158        &self.field
159    }
160
161    fn inner_array(&mut self) -> ArrayRef {
162        self.builder.as_box()
163    }
164
165    fn fast_explode(&self) -> bool {
166        self.fast_explode
167    }
168}