polars_core/chunked_array/builder/list/
anonymous.rs

1use super::*;
2
3pub struct AnonymousListBuilder<'a> {
4    name: PlSmallStr,
5    builder: AnonymousBuilder<'a>,
6    fast_explode: bool,
7    inner_dtype: DtypeMerger,
8}
9
10impl Default for AnonymousListBuilder<'_> {
11    fn default() -> Self {
12        Self::new(PlSmallStr::EMPTY, 0, None)
13    }
14}
15
16impl<'a> AnonymousListBuilder<'a> {
17    pub fn new(name: PlSmallStr, capacity: usize, inner_dtype: Option<DataType>) -> Self {
18        Self {
19            name,
20            builder: AnonymousBuilder::new(capacity),
21            fast_explode: true,
22            inner_dtype: DtypeMerger::new(inner_dtype),
23        }
24    }
25
26    pub fn append_opt_series(&mut self, opt_s: Option<&'a Series>) -> PolarsResult<()> {
27        match opt_s {
28            Some(s) => return self.append_series(s),
29            None => {
30                self.append_null();
31            },
32        }
33        Ok(())
34    }
35
36    pub fn append_opt_array(&mut self, opt_s: Option<&'a dyn Array>) {
37        match opt_s {
38            Some(s) => self.append_array(s),
39            None => {
40                self.append_null();
41            },
42        }
43    }
44
45    pub fn append_array(&mut self, arr: &'a dyn Array) {
46        self.builder.push(arr)
47    }
48
49    #[inline]
50    pub fn append_null(&mut self) {
51        self.fast_explode = false;
52        self.builder.push_null();
53    }
54
55    #[inline]
56    pub fn append_empty(&mut self) {
57        self.fast_explode = false;
58        self.builder.push_empty()
59    }
60
61    pub fn append_series(&mut self, s: &'a Series) -> PolarsResult<()> {
62        match s.dtype() {
63            // Empty arrays tend to be null type and thus differ
64            // if we would push it the concat would fail.
65            DataType::Null if s.is_empty() => self.append_empty(),
66            dt => self.inner_dtype.update(dt)?,
67        }
68        self.builder.push_multiple(s.chunks());
69        Ok(())
70    }
71
72    pub fn finish(&mut self) -> ListChunked {
73        // Don't use self from here on out.
74        let slf = std::mem::take(self);
75        if slf.builder.is_empty() {
76            ListChunked::full_null_with_dtype(
77                slf.name.clone(),
78                0,
79                &slf.inner_dtype.materialize().unwrap_or(DataType::Null),
80            )
81        } else {
82            let inner_dtype = slf.inner_dtype.materialize();
83
84            let inner_dtype_physical = inner_dtype
85                .as_ref()
86                .map(|dt| dt.to_physical().to_arrow(CompatLevel::newest()));
87            let arr = slf.builder.finish(inner_dtype_physical.as_ref()).unwrap();
88
89            let list_dtype_logical = match inner_dtype {
90                None => DataType::from_arrow_dtype(arr.dtype()),
91                Some(dt) => DataType::List(Box::new(dt)),
92            };
93
94            let mut ca = ListChunked::with_chunk(PlSmallStr::EMPTY, arr);
95            if slf.fast_explode {
96                ca.set_fast_explode();
97            }
98            ca.field = Arc::new(Field::new(slf.name.clone(), list_dtype_logical));
99            ca
100        }
101    }
102}
103
104pub struct AnonymousOwnedListBuilder {
105    name: PlSmallStr,
106    builder: AnonymousBuilder<'static>,
107    owned: Vec<Series>,
108    inner_dtype: DtypeMerger,
109    fast_explode: bool,
110}
111
112impl Default for AnonymousOwnedListBuilder {
113    fn default() -> Self {
114        Self::new(PlSmallStr::EMPTY, 0, None)
115    }
116}
117
118impl ListBuilderTrait for AnonymousOwnedListBuilder {
119    fn append_series(&mut self, s: &Series) -> PolarsResult<()> {
120        if s.is_empty() {
121            self.append_empty();
122        } else {
123            unsafe {
124                self.inner_dtype.update(s.dtype())?;
125                self.builder
126                    .push_multiple(&*(s.chunks().as_ref() as *const [ArrayRef]));
127            }
128            // This make sure that the underlying ArrayRef's are not dropped.
129            self.owned.push(s.clone());
130        }
131        Ok(())
132    }
133
134    #[inline]
135    fn append_null(&mut self) {
136        self.fast_explode = false;
137        self.builder.push_null()
138    }
139
140    fn finish(&mut self) -> ListChunked {
141        let inner_dtype = std::mem::take(&mut self.inner_dtype).materialize();
142        // Don't use self from here on out.
143        let slf = std::mem::take(self);
144        let inner_dtype_physical = inner_dtype
145            .as_ref()
146            .map(|dt| dt.to_physical().to_arrow(CompatLevel::newest()));
147        let arr = slf.builder.finish(inner_dtype_physical.as_ref()).unwrap();
148
149        let list_dtype_logical = match inner_dtype {
150            None => DataType::from_arrow_dtype(arr.dtype()),
151            Some(dt) => DataType::List(Box::new(dt)),
152        };
153
154        let mut ca = ListChunked::with_chunk(PlSmallStr::EMPTY, arr);
155        if slf.fast_explode {
156            ca.set_fast_explode();
157        }
158        ca.field = Arc::new(Field::new(slf.name.clone(), list_dtype_logical));
159        ca
160    }
161}
162
163impl AnonymousOwnedListBuilder {
164    pub fn new(name: PlSmallStr, capacity: usize, inner_dtype: Option<DataType>) -> Self {
165        Self {
166            name,
167            builder: AnonymousBuilder::new(capacity),
168            owned: Vec::with_capacity(capacity),
169            inner_dtype: DtypeMerger::new(inner_dtype),
170            fast_explode: true,
171        }
172    }
173
174    #[inline]
175    pub fn append_empty(&mut self) {
176        self.fast_explode = false;
177        self.builder.push_empty()
178    }
179}