arrow_cast/cast/
run_array.rs1use crate::cast::*;
6use arrow_ord::partition::partition;
7
8pub(crate) fn run_end_encoded_cast<K: RunEndIndexType>(
11 array: &dyn Array,
12 to_type: &DataType,
13 cast_options: &CastOptions,
14) -> Result<ArrayRef, ArrowError> {
15 match array.data_type() {
16 DataType::RunEndEncoded(_, _) => {
17 let run_array = array.as_run::<K>();
18
19 match to_type {
20 DataType::RunEndEncoded(target_index_field, target_value_field) => {
22 let values = run_array.values_slice();
23 let cast_values = cast_with_options(
24 values.as_ref(),
25 target_value_field.data_type(),
26 cast_options,
27 )?;
28
29 let run_ends_array =
30 PrimitiveArray::<K>::from_iter_values(run_array.run_ends().sliced_values());
31 let cast_run_ends = cast_with_options(
32 &run_ends_array,
33 target_index_field.data_type(),
34 cast_options,
35 )?;
36 let new_run_array: ArrayRef = match target_index_field.data_type() {
37 DataType::Int16 => {
38 let re = cast_run_ends.as_primitive::<Int16Type>();
39 Arc::new(RunArray::<Int16Type>::try_new(re, cast_values.as_ref())?)
40 }
41 DataType::Int32 => {
42 let re = cast_run_ends.as_primitive::<Int32Type>();
43 Arc::new(RunArray::<Int32Type>::try_new(re, cast_values.as_ref())?)
44 }
45 DataType::Int64 => {
46 let re = cast_run_ends.as_primitive::<Int64Type>();
47 Arc::new(RunArray::<Int64Type>::try_new(re, cast_values.as_ref())?)
48 }
49 _ => {
50 return Err(ArrowError::InvalidArgumentError(
51 "Run-end type must be i16, i32, or i64".to_string(),
52 ));
53 }
54 };
55 Ok(new_run_array)
56 }
57
58 _ => {
60 let values = run_array.values();
61 let len = run_array.len();
62 let offset = run_array.offset();
63 let run_ends = run_array.run_ends().values();
64
65 let mut indices = Vec::with_capacity(len);
66 let mut physical_idx = run_array.get_start_physical_index();
67
68 for logical_idx in offset..offset + len {
69 if logical_idx == run_ends[physical_idx].as_usize() {
70 physical_idx += 1;
73 }
74 indices.push(physical_idx as i32);
75 }
76
77 let taken = take(&values, &Int32Array::from_iter_values(indices), None)?;
78 if taken.data_type() != to_type {
79 cast_with_options(taken.as_ref(), to_type, cast_options)
80 } else {
81 Ok(taken)
82 }
83 }
84 }
85 }
86
87 _ => unreachable!(
88 "cast_with_options only calls run_end_encoded_cast for RunEndEncoded source arrays"
89 ),
90 }
91}
92
93pub(crate) fn cast_to_run_end_encoded<K: RunEndIndexType>(
96 array: &ArrayRef,
97 value_type: &DataType,
98 cast_options: &CastOptions,
99) -> Result<ArrayRef, ArrowError> {
100 let mut run_ends_builder = PrimitiveBuilder::<K>::new();
101
102 let cast_array = if array.data_type() == value_type {
104 array
105 } else {
106 &cast_with_options(array, value_type, cast_options)?
107 };
108
109 if cast_array.is_empty() {
111 let empty_run_ends = run_ends_builder.finish();
112 let empty_values = make_array(ArrayData::new_empty(value_type));
113 return Ok(Arc::new(RunArray::<K>::try_new(
114 &empty_run_ends,
115 empty_values.as_ref(),
116 )?));
117 }
118
119 if let DataType::RunEndEncoded(_, _) = array.data_type() {
121 unreachable!(
122 "cast_with_options handles RunEndEncoded source arrays with run_end_encoded_cast first"
123 );
124 }
125
126 let partitions = partition(&[Arc::clone(cast_array)])?;
128 let size = partitions.len();
129 let mut run_ends = Vec::with_capacity(size);
130 let mut values_indexes = Vec::with_capacity(size);
131 let mut last_partition_end = 0;
132 for partition in partitions.ranges() {
133 values_indexes.push(last_partition_end);
134 run_ends.push(partition.end);
135 last_partition_end = partition.end;
136 }
137
138 for run_end in run_ends {
140 run_ends_builder.append_value(K::Native::from_usize(run_end).ok_or_else(|| {
141 ArrowError::CastError(format!("Run end index out of range: {run_end}"))
142 })?);
143 }
144 let run_ends_array = run_ends_builder.finish();
145 let indices = PrimitiveArray::<UInt32Type>::from_iter_values(
147 values_indexes.iter().map(|&idx| idx as u32),
148 );
149 let values_array = take(&cast_array, &indices, None)?;
150
151 let run_array = RunArray::<K>::try_new(&run_ends_array, values_array.as_ref())?;
153 Ok(Arc::new(run_array))
154}