1use std::sync::Arc;
2
3use polars_arrow::array::builder::ShareStrategy;
4use polars_utils::IdxSize;
5
6use crate::frame::DataFrame;
7use crate::prelude::*;
8use crate::schema::Schema;
9use crate::series::builder::SeriesBuilder;
10
11pub struct DataFrameBuilder {
12 schema: Arc<Schema>,
13 builders: Vec<SeriesBuilder>,
14 height: usize,
15}
16
17impl DataFrameBuilder {
18 pub fn new(schema: Arc<Schema>) -> Self {
19 let builders = schema
20 .iter_values()
21 .map(|dt| SeriesBuilder::new(dt.clone()))
22 .collect();
23 Self {
24 schema,
25 builders,
26 height: 0,
27 }
28 }
29
30 pub fn reserve(&mut self, additional: usize) {
31 for builder in &mut self.builders {
32 builder.reserve(additional);
33 }
34 }
35
36 pub fn freeze(self) -> DataFrame {
37 let columns = self
38 .schema
39 .iter_names()
40 .zip(self.builders)
41 .map(|(n, b)| {
42 let s = b.freeze(n.clone());
43 assert_eq!(s.len(), self.height);
44 Column::from(s)
45 })
46 .collect();
47
48 unsafe { DataFrame::new_unchecked(self.height, columns) }
51 }
52
53 pub fn freeze_reset(&mut self) -> DataFrame {
54 let columns = self
55 .schema
56 .iter_names()
57 .zip(&mut self.builders)
58 .map(|(n, b)| {
59 let s = b.freeze_reset(n.clone());
60 assert!(s.len() == self.height);
61 Column::from(s)
62 })
63 .collect();
64
65 let out = unsafe { DataFrame::new_unchecked(self.height, columns) };
68 self.height = 0;
69 out
70 }
71
72 pub fn len(&self) -> usize {
73 self.height
74 }
75
76 pub fn is_empty(&self) -> bool {
77 self.height == 0
78 }
79
80 pub fn extend(&mut self, other: &DataFrame, share: ShareStrategy) {
83 self.subslice_extend(other, 0, other.height(), share);
84 }
85
86 pub fn subslice_extend(
89 &mut self,
90 other: &DataFrame,
91 start: usize,
92 length: usize,
93 share: ShareStrategy,
94 ) {
95 let columns = other.columns();
96 assert!(self.builders.len() == columns.len());
97 for (builder, column) in self.builders.iter_mut().zip(columns) {
98 match column {
99 Column::Series(s) => {
100 builder.subslice_extend(s, start, length, share);
101 },
102 Column::Scalar(sc) => {
103 let len = sc.len().saturating_sub(start).min(length);
104 let scalar_as_series = sc.scalar().clone().into_series(PlSmallStr::default());
105 builder.subslice_extend_each_repeated(&scalar_as_series, 0, 1, len, share);
106 },
107 }
108 }
109
110 self.height += length.min(other.height().saturating_sub(start));
111 }
112
113 pub fn subslice_extend_repeated(
116 &mut self,
117 other: &DataFrame,
118 start: usize,
119 length: usize,
120 repeats: usize,
121 share: ShareStrategy,
122 ) {
123 let columns = other.columns();
124 assert!(self.builders.len() == columns.len());
125 for (builder, column) in self.builders.iter_mut().zip(columns) {
126 match column {
127 Column::Series(s) => {
128 builder.subslice_extend_repeated(s, start, length, repeats, share);
129 },
130 Column::Scalar(sc) => {
131 let len = sc.len().saturating_sub(start).min(length);
132 let scalar_as_series = sc.scalar().clone().into_series(PlSmallStr::default());
133 builder.subslice_extend_each_repeated(
134 &scalar_as_series,
135 0,
136 1,
137 len * repeats,
138 share,
139 );
140 },
141 }
142 }
143
144 self.height += length.min(other.height().saturating_sub(start)) * repeats;
145 }
146
147 pub fn subslice_extend_each_repeated(
151 &mut self,
152 other: &DataFrame,
153 start: usize,
154 length: usize,
155 repeats: usize,
156 share: ShareStrategy,
157 ) {
158 let columns = other.columns();
159 assert!(self.builders.len() == columns.len());
160 for (builder, column) in self.builders.iter_mut().zip(columns) {
161 match column {
162 Column::Series(s) => {
163 builder.subslice_extend_each_repeated(s, start, length, repeats, share);
164 },
165 Column::Scalar(sc) => {
166 let len = sc.len().saturating_sub(start).min(length);
167 let scalar_as_series = sc.scalar().clone().into_series(PlSmallStr::default());
168 builder.subslice_extend_each_repeated(
169 &scalar_as_series,
170 0,
171 1,
172 len * repeats,
173 share,
174 );
175 },
176 }
177 }
178
179 self.height += length.min(other.height().saturating_sub(start)) * repeats;
180 }
181
182 pub unsafe fn gather_extend(
190 &mut self,
191 other: &DataFrame,
192 idxs: &[IdxSize],
193 share: ShareStrategy,
194 ) {
195 let columns = other.columns();
196 assert!(self.builders.len() == columns.len());
197 for (builder, column) in self.builders.iter_mut().zip(columns) {
198 match column {
199 Column::Series(s) => {
200 builder.gather_extend(s, idxs, share);
201 },
202 Column::Scalar(sc) => {
203 let scalar_as_series = sc.scalar().clone().into_series(PlSmallStr::default());
204 builder.subslice_extend_each_repeated(
205 &scalar_as_series,
206 0,
207 1,
208 idxs.len(),
209 share,
210 );
211 },
212 }
213 }
214
215 self.height += idxs.len();
216 }
217
218 pub fn opt_gather_extend(&mut self, other: &DataFrame, idxs: &[IdxSize], share: ShareStrategy) {
224 let mut trans_idxs = Vec::new();
225 let columns = other.columns();
226 assert!(self.builders.len() == columns.len());
227 for (builder, column) in self.builders.iter_mut().zip(columns) {
228 match column {
229 Column::Series(s) => {
230 builder.opt_gather_extend(s, idxs, share);
231 },
232 Column::Scalar(sc) => {
233 let scalar_as_series = sc.scalar().clone().into_series(PlSmallStr::default());
234 for idx_chunk in idxs.chunks(4096) {
237 trans_idxs.clear();
238 trans_idxs.extend(
239 idx_chunk
240 .iter()
241 .map(|idx| ((*idx as usize) >= sc.len()) as IdxSize),
242 );
243 builder.opt_gather_extend(&scalar_as_series, &trans_idxs, share);
244 }
245 },
246 }
247 }
248
249 self.height += idxs.len();
250 }
251}