polars_core/frame/row/
av_buffer.rs

1use std::hint::unreachable_unchecked;
2
3use arrow::bitmap::BitmapBuilder;
4#[cfg(feature = "dtype-struct")]
5use polars_utils::pl_str::PlSmallStr;
6
7use super::*;
8use crate::chunked_array::builder::NullChunkedBuilder;
9#[cfg(feature = "dtype-struct")]
10use crate::prelude::any_value::arr_to_any_value;
11
12#[derive(Clone)]
13pub enum AnyValueBuffer<'a> {
14    Boolean(BooleanChunkedBuilder),
15    #[cfg(feature = "dtype-i8")]
16    Int8(PrimitiveChunkedBuilder<Int8Type>),
17    #[cfg(feature = "dtype-i16")]
18    Int16(PrimitiveChunkedBuilder<Int16Type>),
19    Int32(PrimitiveChunkedBuilder<Int32Type>),
20    Int64(PrimitiveChunkedBuilder<Int64Type>),
21    #[cfg(feature = "dtype-u8")]
22    UInt8(PrimitiveChunkedBuilder<UInt8Type>),
23    #[cfg(feature = "dtype-u16")]
24    UInt16(PrimitiveChunkedBuilder<UInt16Type>),
25    UInt32(PrimitiveChunkedBuilder<UInt32Type>),
26    UInt64(PrimitiveChunkedBuilder<UInt64Type>),
27    #[cfg(feature = "dtype-date")]
28    Date(PrimitiveChunkedBuilder<Int32Type>),
29    #[cfg(feature = "dtype-datetime")]
30    Datetime(
31        PrimitiveChunkedBuilder<Int64Type>,
32        TimeUnit,
33        Option<TimeZone>,
34    ),
35    #[cfg(feature = "dtype-duration")]
36    Duration(PrimitiveChunkedBuilder<Int64Type>, TimeUnit),
37    #[cfg(feature = "dtype-time")]
38    Time(PrimitiveChunkedBuilder<Int64Type>),
39    Float32(PrimitiveChunkedBuilder<Float32Type>),
40    Float64(PrimitiveChunkedBuilder<Float64Type>),
41    String(StringChunkedBuilder),
42    Null(NullChunkedBuilder),
43    All(DataType, Vec<AnyValue<'a>>),
44}
45
46impl<'a> AnyValueBuffer<'a> {
47    #[inline]
48    pub fn add(&mut self, val: AnyValue<'a>) -> Option<()> {
49        use AnyValueBuffer::*;
50        match (self, val) {
51            (Boolean(builder), AnyValue::Null) => builder.append_null(),
52            (Boolean(builder), AnyValue::Boolean(v)) => builder.append_value(v),
53            (Boolean(builder), val) => {
54                let v = val.extract::<u8>()?;
55                builder.append_value(v == 1)
56            },
57            (Int32(builder), AnyValue::Null) => builder.append_null(),
58            (Int32(builder), val) => builder.append_value(val.extract()?),
59            (Int64(builder), AnyValue::Null) => builder.append_null(),
60            (Int64(builder), val) => builder.append_value(val.extract()?),
61            (UInt32(builder), AnyValue::Null) => builder.append_null(),
62            (UInt32(builder), val) => builder.append_value(val.extract()?),
63            (UInt64(builder), AnyValue::Null) => builder.append_null(),
64            (UInt64(builder), val) => builder.append_value(val.extract()?),
65            (Float32(builder), AnyValue::Null) => builder.append_null(),
66            (Float64(builder), AnyValue::Null) => builder.append_null(),
67            (Float32(builder), val) => builder.append_value(val.extract()?),
68            (Float64(builder), val) => builder.append_value(val.extract()?),
69            (String(builder), AnyValue::String(v)) => builder.append_value(v),
70            (String(builder), AnyValue::StringOwned(v)) => builder.append_value(v.as_str()),
71            (String(builder), AnyValue::Null) => builder.append_null(),
72            #[cfg(feature = "dtype-i8")]
73            (Int8(builder), AnyValue::Null) => builder.append_null(),
74            #[cfg(feature = "dtype-i8")]
75            (Int8(builder), val) => builder.append_value(val.extract()?),
76            #[cfg(feature = "dtype-i16")]
77            (Int16(builder), AnyValue::Null) => builder.append_null(),
78            #[cfg(feature = "dtype-i16")]
79            (Int16(builder), val) => builder.append_value(val.extract()?),
80            #[cfg(feature = "dtype-u8")]
81            (UInt8(builder), AnyValue::Null) => builder.append_null(),
82            #[cfg(feature = "dtype-u8")]
83            (UInt8(builder), val) => builder.append_value(val.extract()?),
84            #[cfg(feature = "dtype-u16")]
85            (UInt16(builder), AnyValue::Null) => builder.append_null(),
86            #[cfg(feature = "dtype-u16")]
87            (UInt16(builder), val) => builder.append_value(val.extract()?),
88            #[cfg(feature = "dtype-date")]
89            (Date(builder), AnyValue::Null) => builder.append_null(),
90            #[cfg(feature = "dtype-date")]
91            (Date(builder), AnyValue::Date(v)) => builder.append_value(v),
92            #[cfg(feature = "dtype-date")]
93            (Date(builder), val) if val.is_primitive_numeric() => {
94                builder.append_value(val.extract()?)
95            },
96            #[cfg(feature = "dtype-datetime")]
97            (Datetime(builder, _, _), AnyValue::Null) => builder.append_null(),
98            #[cfg(feature = "dtype-datetime")]
99            (
100                Datetime(builder, tu_l, _),
101                AnyValue::Datetime(v, tu_r, _) | AnyValue::DatetimeOwned(v, tu_r, _),
102            ) => {
103                // we convert right tu to left tu
104                // so we swap.
105                let v = convert_time_units(v, tu_r, *tu_l);
106                builder.append_value(v)
107            },
108            #[cfg(feature = "dtype-datetime")]
109            (Datetime(builder, _, _), val) if val.is_primitive_numeric() => {
110                builder.append_value(val.extract()?)
111            },
112            #[cfg(feature = "dtype-duration")]
113            (Duration(builder, _), AnyValue::Null) => builder.append_null(),
114            #[cfg(feature = "dtype-duration")]
115            (Duration(builder, tu_l), AnyValue::Duration(v, tu_r)) => {
116                let v = convert_time_units(v, tu_r, *tu_l);
117                builder.append_value(v)
118            },
119            #[cfg(feature = "dtype-duration")]
120            (Duration(builder, _), val) if val.is_primitive_numeric() => {
121                builder.append_value(val.extract()?)
122            },
123            #[cfg(feature = "dtype-time")]
124            (Time(builder), AnyValue::Time(v)) => builder.append_value(v),
125            #[cfg(feature = "dtype-time")]
126            (Time(builder), AnyValue::Null) => builder.append_null(),
127            #[cfg(feature = "dtype-time")]
128            (Time(builder), val) if val.is_primitive_numeric() => {
129                builder.append_value(val.extract()?)
130            },
131            (Null(builder), AnyValue::Null) => builder.append_null(),
132            // Struct and List can be recursive so use AnyValues for that
133            (All(_, vals), v) => vals.push(v.into_static()),
134
135            // dynamic types
136            (String(builder), av) => match av {
137                AnyValue::Int64(v) => builder.append_value(format!("{v}")),
138                AnyValue::Float64(v) => builder.append_value(format!("{v}")),
139                AnyValue::Boolean(true) => builder.append_value("true"),
140                AnyValue::Boolean(false) => builder.append_value("false"),
141                _ => return None,
142            },
143            _ => return None,
144        };
145        Some(())
146    }
147
148    pub(crate) fn add_fallible(&mut self, val: &AnyValue<'a>) -> PolarsResult<()> {
149        self.add(val.clone()).ok_or_else(|| {
150            polars_err!(
151                ComputeError: "could not append value: {} of type: {} to the builder; make sure that all rows \
152                have the same schema or consider increasing `infer_schema_length`\n\
153                \n\
154                it might also be that a value overflows the data-type's capacity", val, val.dtype()
155            )
156        })
157    }
158
159    pub fn reset(&mut self, capacity: usize, strict: bool) -> PolarsResult<Series> {
160        use AnyValueBuffer::*;
161        let out = match self {
162            Boolean(b) => {
163                let mut new = BooleanChunkedBuilder::new(b.field.name().clone(), capacity);
164                std::mem::swap(&mut new, b);
165                new.finish().into_series()
166            },
167            Int32(b) => {
168                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
169                std::mem::swap(&mut new, b);
170                new.finish().into_series()
171            },
172            Int64(b) => {
173                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
174                std::mem::swap(&mut new, b);
175                new.finish().into_series()
176            },
177            UInt32(b) => {
178                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
179                std::mem::swap(&mut new, b);
180                new.finish().into_series()
181            },
182            UInt64(b) => {
183                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
184                std::mem::swap(&mut new, b);
185                new.finish().into_series()
186            },
187            #[cfg(feature = "dtype-date")]
188            Date(b) => {
189                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
190                std::mem::swap(&mut new, b);
191                new.finish().into_date().into_series()
192            },
193            #[cfg(feature = "dtype-datetime")]
194            Datetime(b, tu, tz) => {
195                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
196                std::mem::swap(&mut new, b);
197                let tz = if capacity > 0 {
198                    tz.clone()
199                } else {
200                    std::mem::take(tz)
201                };
202                new.finish().into_datetime(*tu, tz).into_series()
203            },
204            #[cfg(feature = "dtype-duration")]
205            Duration(b, tu) => {
206                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
207                std::mem::swap(&mut new, b);
208                new.finish().into_duration(*tu).into_series()
209            },
210            #[cfg(feature = "dtype-time")]
211            Time(b) => {
212                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
213                std::mem::swap(&mut new, b);
214                new.finish().into_time().into_series()
215            },
216            Float32(b) => {
217                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
218                std::mem::swap(&mut new, b);
219                new.finish().into_series()
220            },
221            Float64(b) => {
222                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
223                std::mem::swap(&mut new, b);
224                new.finish().into_series()
225            },
226            String(b) => {
227                let mut new = StringChunkedBuilder::new(b.field.name().clone(), capacity);
228                std::mem::swap(&mut new, b);
229                new.finish().into_series()
230            },
231            #[cfg(feature = "dtype-i8")]
232            Int8(b) => {
233                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
234                std::mem::swap(&mut new, b);
235                new.finish().into_series()
236            },
237            #[cfg(feature = "dtype-i16")]
238            Int16(b) => {
239                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
240                std::mem::swap(&mut new, b);
241                new.finish().into_series()
242            },
243            #[cfg(feature = "dtype-u8")]
244            UInt8(b) => {
245                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
246                std::mem::swap(&mut new, b);
247                new.finish().into_series()
248            },
249            #[cfg(feature = "dtype-u16")]
250            UInt16(b) => {
251                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
252                std::mem::swap(&mut new, b);
253                new.finish().into_series()
254            },
255            Null(b) => {
256                let mut new = NullChunkedBuilder::new(b.field.name().clone(), 0);
257                std::mem::swap(&mut new, b);
258                new.finish().into_series()
259            },
260            All(dtype, vals) => {
261                let out =
262                    Series::from_any_values_and_dtype(PlSmallStr::EMPTY, vals, dtype, strict)?;
263                let mut new = Vec::with_capacity(capacity);
264                std::mem::swap(&mut new, vals);
265                out
266            },
267        };
268        Ok(out)
269    }
270
271    pub fn into_series(mut self) -> Series {
272        self.reset(0, false).unwrap()
273    }
274
275    pub fn new(dtype: &DataType, capacity: usize) -> AnyValueBuffer<'a> {
276        (dtype, capacity).into()
277    }
278}
279
280// datatype and length
281impl From<(&DataType, usize)> for AnyValueBuffer<'_> {
282    fn from(a: (&DataType, usize)) -> Self {
283        let (dt, len) = a;
284        use DataType::*;
285        match dt {
286            Boolean => AnyValueBuffer::Boolean(BooleanChunkedBuilder::new(PlSmallStr::EMPTY, len)),
287            Int32 => AnyValueBuffer::Int32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
288            Int64 => AnyValueBuffer::Int64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
289            UInt32 => AnyValueBuffer::UInt32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
290            UInt64 => AnyValueBuffer::UInt64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
291            #[cfg(feature = "dtype-i8")]
292            Int8 => AnyValueBuffer::Int8(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
293            #[cfg(feature = "dtype-i16")]
294            Int16 => AnyValueBuffer::Int16(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
295            #[cfg(feature = "dtype-u8")]
296            UInt8 => AnyValueBuffer::UInt8(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
297            #[cfg(feature = "dtype-u16")]
298            UInt16 => AnyValueBuffer::UInt16(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
299            #[cfg(feature = "dtype-date")]
300            Date => AnyValueBuffer::Date(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
301            #[cfg(feature = "dtype-datetime")]
302            Datetime(tu, tz) => AnyValueBuffer::Datetime(
303                PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len),
304                *tu,
305                tz.clone(),
306            ),
307            #[cfg(feature = "dtype-duration")]
308            Duration(tu) => {
309                AnyValueBuffer::Duration(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len), *tu)
310            },
311            #[cfg(feature = "dtype-time")]
312            Time => AnyValueBuffer::Time(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len)),
313            Float32 => {
314                AnyValueBuffer::Float32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
315            },
316            Float64 => {
317                AnyValueBuffer::Float64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
318            },
319            String => AnyValueBuffer::String(StringChunkedBuilder::new(PlSmallStr::EMPTY, len)),
320            Null => AnyValueBuffer::Null(NullChunkedBuilder::new(PlSmallStr::EMPTY, 0)),
321            // Struct and List can be recursive so use AnyValues for that
322            dt => AnyValueBuffer::All(dt.clone(), Vec::with_capacity(len)),
323        }
324    }
325}
326
327/// An [`AnyValueBuffer`] that should be used when we trust the builder
328#[derive(Clone)]
329pub enum AnyValueBufferTrusted<'a> {
330    Boolean(BooleanChunkedBuilder),
331    #[cfg(feature = "dtype-i8")]
332    Int8(PrimitiveChunkedBuilder<Int8Type>),
333    #[cfg(feature = "dtype-i16")]
334    Int16(PrimitiveChunkedBuilder<Int16Type>),
335    Int32(PrimitiveChunkedBuilder<Int32Type>),
336    Int64(PrimitiveChunkedBuilder<Int64Type>),
337    #[cfg(feature = "dtype-u8")]
338    UInt8(PrimitiveChunkedBuilder<UInt8Type>),
339    #[cfg(feature = "dtype-u16")]
340    UInt16(PrimitiveChunkedBuilder<UInt16Type>),
341    UInt32(PrimitiveChunkedBuilder<UInt32Type>),
342    UInt64(PrimitiveChunkedBuilder<UInt64Type>),
343    Float32(PrimitiveChunkedBuilder<Float32Type>),
344    Float64(PrimitiveChunkedBuilder<Float64Type>),
345    String(StringChunkedBuilder),
346    #[cfg(feature = "dtype-struct")]
347    // not the trusted variant!
348    Struct(BitmapBuilder, Vec<(AnyValueBuffer<'a>, PlSmallStr)>),
349    Null(NullChunkedBuilder),
350    All(DataType, Vec<AnyValue<'a>>),
351}
352
353impl<'a> AnyValueBufferTrusted<'a> {
354    pub fn new(dtype: &DataType, len: usize) -> Self {
355        (dtype, len).into()
356    }
357
358    #[inline]
359    unsafe fn add_null(&mut self) {
360        use AnyValueBufferTrusted::*;
361        match self {
362            Boolean(builder) => builder.append_null(),
363            #[cfg(feature = "dtype-i8")]
364            Int8(builder) => builder.append_null(),
365            #[cfg(feature = "dtype-i16")]
366            Int16(builder) => builder.append_null(),
367            Int32(builder) => builder.append_null(),
368            Int64(builder) => builder.append_null(),
369            #[cfg(feature = "dtype-u8")]
370            UInt8(builder) => builder.append_null(),
371            #[cfg(feature = "dtype-u16")]
372            UInt16(builder) => builder.append_null(),
373            UInt32(builder) => builder.append_null(),
374            UInt64(builder) => builder.append_null(),
375            Float32(builder) => builder.append_null(),
376            Float64(builder) => builder.append_null(),
377            String(builder) => builder.append_null(),
378            #[cfg(feature = "dtype-struct")]
379            Struct(outer_validity, builders) => {
380                outer_validity.push(false);
381                for (b, _) in builders.iter_mut() {
382                    b.add(AnyValue::Null);
383                }
384            },
385            Null(builder) => builder.append_null(),
386            All(_, vals) => vals.push(AnyValue::Null),
387        }
388    }
389
390    #[inline]
391    unsafe fn add_physical(&mut self, val: &AnyValue<'_>) {
392        use AnyValueBufferTrusted::*;
393        match self {
394            Boolean(builder) => {
395                let AnyValue::Boolean(v) = val else {
396                    unreachable_unchecked()
397                };
398                builder.append_value(*v)
399            },
400            #[cfg(feature = "dtype-i8")]
401            Int8(builder) => {
402                let AnyValue::Int8(v) = val else {
403                    unreachable_unchecked()
404                };
405                builder.append_value(*v)
406            },
407            #[cfg(feature = "dtype-i16")]
408            Int16(builder) => {
409                let AnyValue::Int16(v) = val else {
410                    unreachable_unchecked()
411                };
412                builder.append_value(*v)
413            },
414            Int32(builder) => {
415                let AnyValue::Int32(v) = val else {
416                    unreachable_unchecked()
417                };
418                builder.append_value(*v)
419            },
420            Int64(builder) => {
421                let AnyValue::Int64(v) = val else {
422                    unreachable_unchecked()
423                };
424                builder.append_value(*v)
425            },
426            #[cfg(feature = "dtype-u8")]
427            UInt8(builder) => {
428                let AnyValue::UInt8(v) = val else {
429                    unreachable_unchecked()
430                };
431                builder.append_value(*v)
432            },
433            #[cfg(feature = "dtype-u16")]
434            UInt16(builder) => {
435                let AnyValue::UInt16(v) = val else {
436                    unreachable_unchecked()
437                };
438                builder.append_value(*v)
439            },
440            UInt32(builder) => {
441                let AnyValue::UInt32(v) = val else {
442                    unreachable_unchecked()
443                };
444                builder.append_value(*v)
445            },
446            UInt64(builder) => {
447                let AnyValue::UInt64(v) = val else {
448                    unreachable_unchecked()
449                };
450                builder.append_value(*v)
451            },
452            Float32(builder) => {
453                let AnyValue::Float32(v) = val else {
454                    unreachable_unchecked()
455                };
456                builder.append_value(*v)
457            },
458            Float64(builder) => {
459                let AnyValue::Float64(v) = val else {
460                    unreachable_unchecked()
461                };
462                builder.append_value(*v)
463            },
464            Null(builder) => {
465                let AnyValue::Null = val else {
466                    unreachable_unchecked()
467                };
468                builder.append_null()
469            },
470            _ => unreachable_unchecked(),
471        }
472    }
473
474    /// Will add the [`AnyValue`] into [`Self`] and unpack as the physical type
475    /// belonging to [`Self`]. This should only be used with physical buffers
476    ///
477    /// If a type is not primitive or String, the AnyValues will be converted to static
478    ///
479    /// # Safety
480    /// The caller must ensure that the [`AnyValue`] type exactly matches the `Buffer` type and is owned.
481    #[inline]
482    pub unsafe fn add_unchecked_owned_physical(&mut self, val: &AnyValue<'_>) {
483        use AnyValueBufferTrusted::*;
484        match val {
485            AnyValue::Null => self.add_null(),
486            _ => {
487                match self {
488                    String(builder) => {
489                        let AnyValue::StringOwned(v) = val else {
490                            unreachable_unchecked()
491                        };
492                        builder.append_value(v.as_str())
493                    },
494                    #[cfg(feature = "dtype-struct")]
495                    Struct(outer_validity, builders) => {
496                        let AnyValue::StructOwned(payload) = val else {
497                            unreachable_unchecked()
498                        };
499                        let avs = &*payload.0;
500                        // amortize loop counter
501                        for i in 0..avs.len() {
502                            unsafe {
503                                let (builder, _) = builders.get_unchecked_mut(i);
504                                let av = avs.get_unchecked(i).clone();
505                                // lifetime is bound to 'a
506                                let av = std::mem::transmute::<AnyValue<'_>, AnyValue<'a>>(av);
507                                builder.add(av.clone());
508                            }
509                        }
510                        outer_validity.push(true);
511                    },
512                    All(_, vals) => vals.push(val.clone().into_static()),
513                    _ => self.add_physical(val),
514                }
515            },
516        }
517    }
518
519    /// # Safety
520    /// The caller must ensure that the [`AnyValue`] type exactly matches the `Buffer` type and is borrowed.
521    #[inline]
522    pub unsafe fn add_unchecked_borrowed_physical(&mut self, val: &AnyValue<'_>) {
523        use AnyValueBufferTrusted::*;
524        match val {
525            AnyValue::Null => self.add_null(),
526            _ => {
527                match self {
528                    String(builder) => {
529                        let AnyValue::String(v) = val else {
530                            unreachable_unchecked()
531                        };
532                        builder.append_value(v)
533                    },
534                    #[cfg(feature = "dtype-struct")]
535                    Struct(outer_validity, builders) => {
536                        let AnyValue::Struct(idx, arr, fields) = val else {
537                            unreachable_unchecked()
538                        };
539                        let arrays = arr.values();
540                        // amortize loop counter
541                        for i in 0..fields.len() {
542                            unsafe {
543                                let array = arrays.get_unchecked(i);
544                                let field = fields.get_unchecked(i);
545                                let (builder, _) = builders.get_unchecked_mut(i);
546                                let av = arr_to_any_value(&**array, *idx, &field.dtype);
547                                // lifetime is bound to 'a
548                                let av = std::mem::transmute::<AnyValue<'_>, AnyValue<'a>>(av);
549                                builder.add(av);
550                            }
551                        }
552                        outer_validity.push(true);
553                    },
554                    All(_, vals) => vals.push(val.clone().into_static()),
555                    _ => self.add_physical(val),
556                }
557            },
558        }
559    }
560
561    /// Clear `self` and give `capacity`, returning the old contents as a [`Series`].
562    pub fn reset(&mut self, capacity: usize, strict: bool) -> PolarsResult<Series> {
563        use AnyValueBufferTrusted::*;
564        let out = match self {
565            Boolean(b) => {
566                let mut new = BooleanChunkedBuilder::new(b.field.name().clone(), capacity);
567                std::mem::swap(&mut new, b);
568                new.finish().into_series()
569            },
570            Int32(b) => {
571                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
572                std::mem::swap(&mut new, b);
573                new.finish().into_series()
574            },
575            Int64(b) => {
576                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
577                std::mem::swap(&mut new, b);
578                new.finish().into_series()
579            },
580            UInt32(b) => {
581                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
582                std::mem::swap(&mut new, b);
583                new.finish().into_series()
584            },
585            UInt64(b) => {
586                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
587                std::mem::swap(&mut new, b);
588                new.finish().into_series()
589            },
590            Float32(b) => {
591                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
592                std::mem::swap(&mut new, b);
593                new.finish().into_series()
594            },
595            Float64(b) => {
596                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
597                std::mem::swap(&mut new, b);
598                new.finish().into_series()
599            },
600            String(b) => {
601                let mut new = StringChunkedBuilder::new(b.field.name().clone(), capacity);
602                std::mem::swap(&mut new, b);
603                new.finish().into_series()
604            },
605            #[cfg(feature = "dtype-i8")]
606            Int8(b) => {
607                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
608                std::mem::swap(&mut new, b);
609                new.finish().into_series()
610            },
611            #[cfg(feature = "dtype-i16")]
612            Int16(b) => {
613                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
614                std::mem::swap(&mut new, b);
615                new.finish().into_series()
616            },
617            #[cfg(feature = "dtype-u8")]
618            UInt8(b) => {
619                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
620                std::mem::swap(&mut new, b);
621                new.finish().into_series()
622            },
623            #[cfg(feature = "dtype-u16")]
624            UInt16(b) => {
625                let mut new = PrimitiveChunkedBuilder::new(b.field.name().clone(), capacity);
626                std::mem::swap(&mut new, b);
627                new.finish().into_series()
628            },
629            #[cfg(feature = "dtype-struct")]
630            Struct(outer_validity, b) => {
631                // @Q? Maybe we need to add a length parameter here for ZFS's. I am not very happy
632                // with just setting the length to zero for that case.
633                if b.is_empty() {
634                    return Ok(
635                        StructChunked::from_series(PlSmallStr::EMPTY, 0, [].iter())?.into_series()
636                    );
637                }
638
639                let mut min_len = usize::MAX;
640                let mut max_len = usize::MIN;
641
642                let v = b
643                    .iter_mut()
644                    .map(|(b, name)| {
645                        let mut s = b.reset(capacity, strict)?;
646
647                        min_len = min_len.min(s.len());
648                        max_len = max_len.max(s.len());
649
650                        s.rename(name.clone());
651                        Ok(s)
652                    })
653                    .collect::<PolarsResult<Vec<_>>>()?;
654
655                let length = if min_len == 0 { 0 } else { max_len };
656
657                let old_outer_validity = core::mem::take(outer_validity);
658                outer_validity.reserve(capacity);
659
660                StructChunked::from_series(PlSmallStr::EMPTY, length, v.iter())
661                    .unwrap()
662                    .with_outer_validity(Some(old_outer_validity.freeze()))
663                    .into_series()
664            },
665            Null(b) => {
666                let mut new = NullChunkedBuilder::new(b.field.name().clone(), 0);
667                std::mem::swap(&mut new, b);
668                new.finish().into_series()
669            },
670            All(dtype, vals) => {
671                let mut swap_vals = Vec::with_capacity(capacity);
672                std::mem::swap(vals, &mut swap_vals);
673                Series::from_any_values_and_dtype(PlSmallStr::EMPTY, &swap_vals, dtype, false)
674                    .unwrap()
675            },
676        };
677
678        Ok(out)
679    }
680
681    pub fn into_series(mut self) -> Series {
682        // unwrap: non-strict does not error.
683        self.reset(0, false).unwrap()
684    }
685}
686
687impl From<(&DataType, usize)> for AnyValueBufferTrusted<'_> {
688    fn from(a: (&DataType, usize)) -> Self {
689        let (dt, len) = a;
690        use DataType::*;
691        match dt {
692            Boolean => {
693                AnyValueBufferTrusted::Boolean(BooleanChunkedBuilder::new(PlSmallStr::EMPTY, len))
694            },
695            Int32 => {
696                AnyValueBufferTrusted::Int32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
697            },
698            Int64 => {
699                AnyValueBufferTrusted::Int64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
700            },
701            UInt32 => {
702                AnyValueBufferTrusted::UInt32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
703            },
704            UInt64 => {
705                AnyValueBufferTrusted::UInt64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
706            },
707            #[cfg(feature = "dtype-i8")]
708            Int8 => {
709                AnyValueBufferTrusted::Int8(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
710            },
711            #[cfg(feature = "dtype-i16")]
712            Int16 => {
713                AnyValueBufferTrusted::Int16(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
714            },
715            #[cfg(feature = "dtype-u8")]
716            UInt8 => {
717                AnyValueBufferTrusted::UInt8(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
718            },
719            #[cfg(feature = "dtype-u16")]
720            UInt16 => {
721                AnyValueBufferTrusted::UInt16(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
722            },
723            Float32 => {
724                AnyValueBufferTrusted::Float32(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
725            },
726            Float64 => {
727                AnyValueBufferTrusted::Float64(PrimitiveChunkedBuilder::new(PlSmallStr::EMPTY, len))
728            },
729            String => {
730                AnyValueBufferTrusted::String(StringChunkedBuilder::new(PlSmallStr::EMPTY, len))
731            },
732            #[cfg(feature = "dtype-struct")]
733            Struct(fields) => {
734                let outer_validity = BitmapBuilder::with_capacity(len);
735                let buffers = fields
736                    .iter()
737                    .map(|field| {
738                        let dtype = field.dtype().to_physical();
739                        let buffer: AnyValueBuffer = (&dtype, len).into();
740                        (buffer, field.name.clone())
741                    })
742                    .collect::<Vec<_>>();
743                AnyValueBufferTrusted::Struct(outer_validity, buffers)
744            },
745            // List can be recursive so use AnyValues for that
746            dt => AnyValueBufferTrusted::All(dt.clone(), Vec::with_capacity(len)),
747        }
748    }
749}