polars_core/chunked_array/builder/list/
primitive.rs1use 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 #[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 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 #[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 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 unsafe { values.extend_trusted_len_unchecked(arr.into_iter()) }
150 }
151 });
152 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}