1use std::sync::Arc;
5
6use arrow_array::{make_array, Array, RecordBatch};
7use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer};
8use arrow_data::{ArrayData, ArrayDataBuilder};
9
10pub fn deep_copy_buffer(buffer: &Buffer) -> Buffer {
11 Buffer::from(buffer.as_slice())
12}
13
14fn deep_copy_nulls(nulls: Option<&NullBuffer>) -> Option<NullBuffer> {
15 let nulls = nulls?;
16 let bit_buffer = deep_copy_buffer(nulls.inner().inner());
17 Some(unsafe {
18 NullBuffer::new_unchecked(
19 BooleanBuffer::new(bit_buffer, nulls.offset(), nulls.len()),
20 nulls.null_count(),
21 )
22 })
23}
24
25pub fn deep_copy_array_data(data: &ArrayData) -> ArrayData {
26 let data_type = data.data_type().clone();
27 let len = data.len();
28 let nulls = deep_copy_nulls(data.nulls());
29 let offset = data.offset();
30 let buffers = data
31 .buffers()
32 .iter()
33 .map(deep_copy_buffer)
34 .collect::<Vec<_>>();
35 let child_data = data
36 .child_data()
37 .iter()
38 .map(deep_copy_array_data)
39 .collect::<Vec<_>>();
40 unsafe {
41 ArrayDataBuilder::new(data_type)
42 .len(len)
43 .nulls(nulls)
44 .offset(offset)
45 .buffers(buffers)
46 .child_data(child_data)
47 .build_unchecked()
48 }
49}
50
51pub fn deep_copy_array(array: &dyn Array) -> Arc<dyn Array> {
52 let data = array.to_data();
53 let data = deep_copy_array_data(&data);
54 make_array(data)
55}
56
57pub fn deep_copy_batch(batch: &RecordBatch) -> crate::Result<RecordBatch> {
58 let arrays = batch
59 .columns()
60 .iter()
61 .map(|array| deep_copy_array(array))
62 .collect::<Vec<_>>();
63 RecordBatch::try_new(batch.schema(), arrays)
64}
65
66#[cfg(test)]
67pub mod tests {
68 use std::sync::Arc;
69
70 use arrow_array::{Array, Int32Array};
71
72 #[test]
73 fn test_deep_copy_sliced_array_with_nulls() {
74 let array = Arc::new(Int32Array::from(vec![
75 Some(1),
76 None,
77 Some(3),
78 None,
79 Some(5),
80 ]));
81 let sliced_array = array.slice(1, 3);
82 let copied_array = super::deep_copy_array(&sliced_array);
83 assert_eq!(sliced_array.len(), copied_array.len());
84 assert_eq!(sliced_array.nulls(), copied_array.nulls());
85 }
86}