arrow_cast/cast/
run_array.rs1use crate::cast::*;
19use arrow_ord::partition::partition;
20
21pub(crate) fn run_end_encoded_cast<K: RunEndIndexType>(
24 array: &dyn Array,
25 to_type: &DataType,
26 cast_options: &CastOptions,
27) -> Result<ArrayRef, ArrowError> {
28 match array.data_type() {
29 DataType::RunEndEncoded(_, _) => {
30 let run_array = array
31 .as_any()
32 .downcast_ref::<RunArray<K>>()
33 .ok_or_else(|| ArrowError::CastError("Expected RunArray".to_string()))?;
34
35 let values = run_array.values();
36
37 match to_type {
38 DataType::RunEndEncoded(target_index_field, target_value_field) => {
40 let cast_values =
41 cast_with_options(values, target_value_field.data_type(), cast_options)?;
42
43 let run_ends_array = PrimitiveArray::<K>::from_iter_values(
44 run_array.run_ends().values().iter().copied(),
45 );
46 let cast_run_ends = cast_with_options(
47 &run_ends_array,
48 target_index_field.data_type(),
49 cast_options,
50 )?;
51 let new_run_array: ArrayRef = match target_index_field.data_type() {
52 DataType::Int16 => {
53 let re = cast_run_ends.as_primitive::<Int16Type>();
54 Arc::new(RunArray::<Int16Type>::try_new(re, cast_values.as_ref())?)
55 }
56 DataType::Int32 => {
57 let re = cast_run_ends.as_primitive::<Int32Type>();
58 Arc::new(RunArray::<Int32Type>::try_new(re, cast_values.as_ref())?)
59 }
60 DataType::Int64 => {
61 let re = cast_run_ends.as_primitive::<Int64Type>();
62 Arc::new(RunArray::<Int64Type>::try_new(re, cast_values.as_ref())?)
63 }
64 _ => {
65 return Err(ArrowError::CastError(
66 "Run-end type must be i16, i32, or i64".to_string(),
67 ));
68 }
69 };
70 Ok(Arc::new(new_run_array))
71 }
72
73 _ => {
75 let run_ends = run_array.run_ends().values().to_vec();
76 let mut indices = Vec::with_capacity(run_array.run_ends().len());
77 let mut physical_idx: usize = 0;
78 for logical_idx in 0..run_array.run_ends().len() {
79 if logical_idx == run_ends[physical_idx].as_usize() {
82 physical_idx += 1;
83 }
84 indices.push(physical_idx as i32);
85 }
86
87 let taken = take(&values, &Int32Array::from_iter_values(indices), None)?;
88 if taken.data_type() != to_type {
89 cast_with_options(taken.as_ref(), to_type, cast_options)
90 } else {
91 Ok(taken)
92 }
93 }
94 }
95 }
96
97 _ => Err(ArrowError::CastError(format!(
98 "Cannot cast array of type {:?} to RunEndEncodedArray",
99 array.data_type()
100 ))),
101 }
102}
103
104pub(crate) fn cast_to_run_end_encoded<K: RunEndIndexType>(
107 array: &ArrayRef,
108 value_type: &DataType,
109 cast_options: &CastOptions,
110) -> Result<ArrayRef, ArrowError> {
111 let mut run_ends_builder = PrimitiveBuilder::<K>::new();
112
113 let cast_array = if array.data_type() == value_type {
115 array
116 } else {
117 &cast_with_options(array, value_type, cast_options)?
118 };
119
120 if cast_array.is_empty() {
122 let empty_run_ends = run_ends_builder.finish();
123 let empty_values = make_array(ArrayData::new_empty(value_type));
124 return Ok(Arc::new(RunArray::<K>::try_new(
125 &empty_run_ends,
126 empty_values.as_ref(),
127 )?));
128 }
129
130 if let DataType::RunEndEncoded(_, _) = array.data_type() {
132 return Err(ArrowError::CastError(
133 "Source array is already a RunEndEncoded array, should have been handled by run_end_encoded_cast".to_string()
134 ));
135 }
136
137 let partitions = partition(&[Arc::clone(cast_array)])?;
139 let mut run_ends = Vec::new();
140 let mut values_indexes = Vec::new();
141 let mut last_partition_end = 0;
142 for partition in partitions.ranges() {
143 values_indexes.push(last_partition_end);
144 run_ends.push(partition.end);
145 last_partition_end = partition.end;
146 }
147
148 for run_end in run_ends {
150 run_ends_builder.append_value(K::Native::from_usize(run_end).ok_or_else(|| {
151 ArrowError::CastError(format!("Run end index out of range: {}", run_end))
152 })?);
153 }
154 let run_ends_array = run_ends_builder.finish();
155 let indices = PrimitiveArray::<UInt32Type>::from_iter_values(
157 values_indexes.iter().map(|&idx| idx as u32),
158 );
159 let values_array = take(&cast_array, &indices, None)?;
160
161 let run_array = RunArray::<K>::try_new(&run_ends_array, values_array.as_ref())?;
163 Ok(Arc::new(run_array))
164}