1use std::{any::Any, sync::Arc};
6
7use crate::{ArrayRef, ArrowPrimitiveType, RunArray, types::RunEndIndexType};
8
9use super::{ArrayBuilder, PrimitiveBuilder};
10
11use arrow_buffer::ArrowNativeType;
12
13#[derive(Debug)]
48pub struct PrimitiveRunBuilder<R, V>
49where
50 R: RunEndIndexType,
51 V: ArrowPrimitiveType,
52{
53 run_ends_builder: PrimitiveBuilder<R>,
54 values_builder: PrimitiveBuilder<V>,
55 current_value: Option<V::Native>,
56 current_run_end_index: usize,
57 prev_run_end_index: usize,
58}
59
60impl<R, V> Default for PrimitiveRunBuilder<R, V>
61where
62 R: RunEndIndexType,
63 V: ArrowPrimitiveType,
64{
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl<R, V> PrimitiveRunBuilder<R, V>
71where
72 R: RunEndIndexType,
73 V: ArrowPrimitiveType,
74{
75 pub fn new() -> Self {
77 Self {
78 run_ends_builder: PrimitiveBuilder::new(),
79 values_builder: PrimitiveBuilder::new(),
80 current_value: None,
81 current_run_end_index: 0,
82 prev_run_end_index: 0,
83 }
84 }
85
86 pub fn with_capacity(capacity: usize) -> Self {
90 Self {
91 run_ends_builder: PrimitiveBuilder::with_capacity(capacity),
92 values_builder: PrimitiveBuilder::with_capacity(capacity),
93 current_value: None,
94 current_run_end_index: 0,
95 prev_run_end_index: 0,
96 }
97 }
98
99 pub fn with_data_type(mut self, data_type: arrow_schema::DataType) -> Self {
109 self.values_builder = self.values_builder.with_data_type(data_type);
110 self
111 }
112}
113
114impl<R, V> ArrayBuilder for PrimitiveRunBuilder<R, V>
115where
116 R: RunEndIndexType,
117 V: ArrowPrimitiveType,
118{
119 fn as_any(&self) -> &dyn Any {
121 self
122 }
123
124 fn as_any_mut(&mut self) -> &mut dyn Any {
126 self
127 }
128
129 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
131 self
132 }
133
134 fn len(&self) -> usize {
137 self.current_run_end_index
138 }
139
140 fn finish(&mut self) -> ArrayRef {
142 Arc::new(self.finish())
143 }
144
145 fn finish_cloned(&self) -> ArrayRef {
147 Arc::new(self.finish_cloned())
148 }
149}
150
151impl<R, V> PrimitiveRunBuilder<R, V>
152where
153 R: RunEndIndexType,
154 V: ArrowPrimitiveType,
155{
156 pub fn append_option(&mut self, value: Option<V::Native>) {
158 if self.current_run_end_index == 0 {
159 self.current_run_end_index = 1;
160 self.current_value = value;
161 return;
162 }
163 if self.current_value != value {
164 self.append_run_end();
165 self.current_value = value;
166 }
167
168 self.current_run_end_index += 1;
169 }
170
171 pub fn append_value(&mut self, value: V::Native) {
173 self.append_option(Some(value))
174 }
175
176 pub fn append_null(&mut self) {
178 self.append_option(None)
179 }
180
181 pub fn finish(&mut self) -> RunArray<R> {
187 self.append_run_end();
189
190 self.current_value = None;
192 self.current_run_end_index = 0;
193 self.prev_run_end_index = 0;
194
195 let run_ends_array = self.run_ends_builder.finish();
197 let values_array = self.values_builder.finish();
198 RunArray::<R>::try_new(&run_ends_array, &values_array).unwrap()
199 }
200
201 pub fn finish_cloned(&self) -> RunArray<R> {
207 let mut run_ends_array = self.run_ends_builder.finish_cloned();
208 let mut values_array = self.values_builder.finish_cloned();
209
210 if self.prev_run_end_index != self.current_run_end_index {
212 let mut run_end_builder = run_ends_array.into_builder().unwrap();
213 let mut values_builder = values_array.into_builder().unwrap();
214 self.append_run_end_with_builders(&mut run_end_builder, &mut values_builder);
215 run_ends_array = run_end_builder.finish();
216 values_array = values_builder.finish();
217 }
218
219 RunArray::try_new(&run_ends_array, &values_array).unwrap()
220 }
221
222 fn append_run_end(&mut self) {
224 if self.prev_run_end_index == self.current_run_end_index {
226 return;
227 }
228 let run_end_index = self.run_end_index_as_native();
229 self.run_ends_builder.append_value(run_end_index);
230 self.values_builder.append_option(self.current_value);
231 self.prev_run_end_index = self.current_run_end_index;
232 }
233
234 fn append_run_end_with_builders(
237 &self,
238 run_ends_builder: &mut PrimitiveBuilder<R>,
239 values_builder: &mut PrimitiveBuilder<V>,
240 ) {
241 let run_end_index = self.run_end_index_as_native();
242 run_ends_builder.append_value(run_end_index);
243 values_builder.append_option(self.current_value);
244 }
245
246 fn run_end_index_as_native(&self) -> R::Native {
247 R::Native::from_usize(self.current_run_end_index)
248 .unwrap_or_else(|| panic!(
249 "Cannot convert `current_run_end_index` {} from `usize` to native form of arrow datatype {}",
250 self.current_run_end_index,
251 R::DATA_TYPE
252 ))
253 }
254}
255
256impl<R, V> Extend<Option<V::Native>> for PrimitiveRunBuilder<R, V>
257where
258 R: RunEndIndexType,
259 V: ArrowPrimitiveType,
260{
261 fn extend<T: IntoIterator<Item = Option<V::Native>>>(&mut self, iter: T) {
262 for elem in iter {
263 self.append_option(elem);
264 }
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use arrow_schema::DataType;
271
272 use crate::builder::PrimitiveRunBuilder;
273 use crate::cast::AsArray;
274 use crate::types::{Decimal128Type, Int16Type, TimestampMicrosecondType, UInt32Type};
275 use crate::{Array, Decimal128Array, TimestampMicrosecondArray, UInt32Array};
276
277 #[test]
278 fn test_primitive_ree_array_builder() {
279 let mut builder = PrimitiveRunBuilder::<Int16Type, UInt32Type>::new();
280 builder.append_value(1234);
281 builder.append_value(1234);
282 builder.append_value(1234);
283 builder.append_null();
284 builder.append_value(5678);
285 builder.append_value(5678);
286
287 let array = builder.finish();
288
289 assert_eq!(array.null_count(), 0);
290 assert_eq!(array.logical_null_count(), 1);
291 assert_eq!(array.len(), 6);
292
293 assert_eq!(array.run_ends().values(), &[3, 4, 6]);
294
295 let av = array.values();
296
297 assert!(!av.is_null(0));
298 assert!(av.is_null(1));
299 assert!(!av.is_null(2));
300
301 let ava: &UInt32Array = av.as_primitive::<UInt32Type>();
303
304 assert_eq!(ava, &UInt32Array::from(vec![Some(1234), None, Some(5678)]));
305 }
306
307 #[test]
308 fn test_extend() {
309 let mut builder = PrimitiveRunBuilder::<Int16Type, Int16Type>::new();
310 builder.extend([1, 2, 2, 5, 5, 4, 4].into_iter().map(Some));
311 builder.extend([4, 4, 6, 2].into_iter().map(Some));
312 let array = builder.finish();
313
314 assert_eq!(array.len(), 11);
315 assert_eq!(array.null_count(), 0);
316 assert_eq!(array.logical_null_count(), 0);
317 assert_eq!(array.run_ends().values(), &[1, 3, 5, 9, 10, 11]);
318 assert_eq!(
319 array.values().as_primitive::<Int16Type>().values(),
320 &[1, 2, 5, 4, 6, 2]
321 );
322 }
323
324 #[test]
325 fn test_reuse_after_finish() {
326 let mut builder = PrimitiveRunBuilder::<Int16Type, Int16Type>::new();
327 builder.extend([1, 2, 3].into_iter().map(Some));
328 builder.finish();
329
330 builder.extend([7, 7, 7].into_iter().map(Some));
332 let array = builder.finish();
333 assert_eq!(array.len(), 3);
334 assert_eq!(array.run_ends().values(), &[3]);
335 assert_eq!(array.values().as_primitive::<Int16Type>().values(), &[7]);
336
337 assert_eq!(builder.finish().len(), 0);
339 }
340
341 #[test]
342 #[should_panic(expected = "incompatible data type for builder")]
343 fn test_override_data_type_invalid() {
344 PrimitiveRunBuilder::<Int16Type, UInt32Type>::new().with_data_type(DataType::UInt64);
345 }
346
347 #[test]
348 fn test_override_data_type() {
349 PrimitiveRunBuilder::<Int16Type, UInt32Type>::new().with_data_type(DataType::UInt32);
351
352 let mut builder = PrimitiveRunBuilder::<Int16Type, Decimal128Type>::new()
354 .with_data_type(DataType::Decimal128(1, 2));
355 builder.append_value(123);
356 let array = builder.finish();
357 let array = array.downcast::<Decimal128Array>().unwrap();
358 let values = array.values();
359 assert_eq!(values.precision(), 1);
360 assert_eq!(values.scale(), 2);
361
362 let mut builder = PrimitiveRunBuilder::<Int16Type, TimestampMicrosecondType>::new()
364 .with_data_type(DataType::Timestamp(
365 arrow_schema::TimeUnit::Microsecond,
366 Some("Europe/Paris".into()),
367 ));
368 builder.append_value(1);
369 let array = builder.finish();
370 let array = array.downcast::<TimestampMicrosecondArray>().unwrap();
371 let values = array.values();
372 assert_eq!(values.timezone(), Some("Europe/Paris"));
373 }
374
375 #[test]
376 fn test_finish_cloned_keeps_data_type() {
377 let data_type = DataType::Decimal128(5, 2);
378 let mut builder = PrimitiveRunBuilder::<Int16Type, Decimal128Type>::new()
379 .with_data_type(data_type.clone());
380 builder.append_value(123);
382 let array = builder.finish_cloned();
383 assert_eq!(array.values().data_type(), &data_type);
384 }
385}