1use crate::cast::*;
19
20pub(crate) fn cast_values_to_list<O: OffsetSizeTrait>(
26 array: &dyn Array,
27 to: &FieldRef,
28 cast_options: &CastOptions,
29) -> Result<ArrayRef, ArrowError> {
30 if array.len() > O::MAX_OFFSET {
31 return Err(ArrowError::ComputeError(format!(
32 "Offset overflow when casting from {} to {}",
33 array.data_type(),
34 to.data_type()
35 )));
36 }
37 let values = cast_with_options(array, to.data_type(), cast_options)?;
38 let offsets = OffsetBuffer::from_repeated_length(1, values.len());
39 let list = GenericListArray::<O>::try_new(to.clone(), offsets, values, None)?;
40 Ok(Arc::new(list))
41}
42
43pub(crate) fn cast_values_to_list_view<O: OffsetSizeTrait>(
45 array: &dyn Array,
46 to: &FieldRef,
47 cast_options: &CastOptions,
48) -> Result<ArrayRef, ArrowError> {
49 if array.len() > O::MAX_OFFSET {
50 return Err(ArrowError::ComputeError(format!(
51 "Offset overflow when casting from {} to {}",
52 array.data_type(),
53 to.data_type()
54 )));
55 }
56 let values = cast_with_options(array, to.data_type(), cast_options)?;
57 let offsets = (0..values.len())
58 .map(|index| O::usize_as(index))
59 .collect::<Vec<O>>();
60 let list = GenericListViewArray::<O>::try_new(
61 to.clone(),
62 offsets.into(),
63 vec![O::one(); values.len()].into(),
64 values,
65 None,
66 )?;
67 Ok(Arc::new(list))
68}
69
70pub(crate) fn cast_single_element_fixed_size_list_to_values(
75 array: &dyn Array,
76 to: &DataType,
77 cast_options: &CastOptions,
78) -> Result<ArrayRef, ArrowError> {
79 let values = array.as_fixed_size_list().values();
80 cast_with_options(values, to, cast_options)
81}
82
83fn cast_fixed_size_list_to_list_inner<OffsetSize: OffsetSizeTrait, const IS_LIST_VIEW: bool>(
84 array: &dyn Array,
85 to: &FieldRef,
86 cast_options: &CastOptions,
87) -> Result<ArrayRef, ArrowError> {
88 let array = array.as_fixed_size_list();
89 let DataType::FixedSizeList(inner_field, size) = array.data_type() else {
90 unreachable!()
91 };
92 let array = if to != inner_field {
93 let fsl_to = DataType::FixedSizeList(to.clone(), *size);
95 let array = cast_with_options(array, &fsl_to, cast_options)?;
96 array.as_fixed_size_list().clone()
97 } else {
98 array.clone()
99 };
100 if IS_LIST_VIEW {
101 let list: GenericListViewArray<OffsetSize> = array.into();
102 Ok(Arc::new(list))
103 } else {
104 let list: GenericListArray<OffsetSize> = array.into();
105 Ok(Arc::new(list))
106 }
107}
108
109pub(crate) fn cast_fixed_size_list_to_list<OffsetSize: OffsetSizeTrait>(
114 array: &dyn Array,
115 to: &FieldRef,
116 cast_options: &CastOptions,
117) -> Result<ArrayRef, ArrowError> {
118 cast_fixed_size_list_to_list_inner::<OffsetSize, false>(array, to, cast_options)
119}
120
121pub(crate) fn cast_fixed_size_list_to_list_view<OffsetSize: OffsetSizeTrait>(
123 array: &dyn Array,
124 to: &FieldRef,
125 cast_options: &CastOptions,
126) -> Result<ArrayRef, ArrowError> {
127 cast_fixed_size_list_to_list_inner::<OffsetSize, true>(array, to, cast_options)
128}
129
130pub(crate) fn cast_list_to_fixed_size_list<OffsetSize>(
134 array: &dyn Array,
135 field: &FieldRef,
136 size: i32,
137 cast_options: &CastOptions,
138) -> Result<ArrayRef, ArrowError>
139where
140 OffsetSize: OffsetSizeTrait,
141{
142 let array = array.as_list::<OffsetSize>();
143
144 let cap = array.len() * size as usize;
145
146 let mut null_builder = NullBufferBuilder::new(array.len());
147 if let Some(nulls) = array.nulls().filter(|b| b.null_count() > 0) {
148 null_builder.append_buffer(nulls);
149 } else {
150 null_builder.append_n_non_nulls(array.len());
151 }
152
153 let nullable = cast_options.safe || array.null_count() != 0;
155 let values = array.values().to_data();
157 let mut mutable = MutableArrayData::new(vec![&values], nullable, cap);
158 let first_pos = array.offsets()[0].as_usize();
159 let mut last_pos = None;
162
163 for (idx, w) in array.offsets().windows(2).enumerate() {
164 let start_pos = w[0].as_usize();
165 let end_pos = w[1].as_usize();
166 let len = end_pos - start_pos;
167
168 if len != size as usize {
169 if cast_options.safe || array.is_null(idx) {
170 let copy_start = last_pos.unwrap_or(first_pos);
171 if copy_start != start_pos {
172 mutable
174 .try_extend(0, copy_start, start_pos)
175 .map_err(|e| ArrowError::CastError(e.to_string()))?;
176 }
177 mutable
179 .try_extend_nulls(size as _)
180 .map_err(|e| ArrowError::CastError(e.to_string()))?;
181 null_builder.set_bit(idx, false);
182 last_pos = Some(end_pos)
184 } else {
185 return Err(ArrowError::CastError(format!(
186 "Cannot cast to FixedSizeList({size}): value at index {idx} has length {len}",
187 )));
188 }
189 }
190 }
191
192 let values = match last_pos {
193 None => array.values().slice(first_pos, cap), Some(last_pos) => {
195 if mutable.len() != cap {
196 let remaining = cap - mutable.len();
198 mutable
199 .try_extend(0, last_pos, last_pos + remaining)
200 .map_err(|e| ArrowError::CastError(e.to_string()))?;
201 }
202 make_array(mutable.freeze())
203 }
204 };
205
206 let values = cast_with_options(values.as_ref(), field.data_type(), cast_options)?;
208
209 let nulls = null_builder.build();
210 let array = if size == 0 && nulls.is_none() {
213 FixedSizeListArray::try_new_with_length(field.clone(), size, values, nulls, array.len())?
214 } else {
215 FixedSizeListArray::try_new(field.clone(), size, values, nulls)?
216 };
217 Ok(Arc::new(array))
218}
219
220pub(crate) fn cast_list_view_to_fixed_size_list<O: OffsetSizeTrait>(
222 array: &dyn Array,
223 field: &FieldRef,
224 size: i32,
225 cast_options: &CastOptions,
226) -> Result<ArrayRef, ArrowError> {
227 let array = array.as_list_view::<O>();
228
229 let mut null_builder = NullBufferBuilder::new(array.len());
230 if let Some(nulls) = array.nulls().filter(|b| b.null_count() > 0) {
231 null_builder.append_buffer(nulls);
232 } else {
233 null_builder.append_n_non_nulls(array.len());
234 }
235
236 let nullable = cast_options.safe || array.null_count() != 0;
237 let values = array.values().to_data();
238 let cap = array.len() * size as usize;
239 let mut mutable = MutableArrayData::new(vec![&values], nullable, cap);
240
241 for idx in 0..array.len() {
242 let offset = array.value_offset(idx).as_usize();
243 let len = array.value_size(idx).as_usize();
244
245 if len != size as usize {
246 if cast_options.safe || array.is_null(idx) {
248 mutable
249 .try_extend_nulls(size as _)
250 .map_err(|e| ArrowError::CastError(e.to_string()))?;
251 null_builder.set_bit(idx, false);
252 } else {
253 return Err(ArrowError::CastError(format!(
254 "Cannot cast to FixedSizeList({size}): value at index {idx} has length {len}",
255 )));
256 }
257 } else {
258 mutable
259 .try_extend(0, offset, offset + len)
260 .map_err(|e| ArrowError::CastError(e.to_string()))?;
261 }
262 }
263
264 let values = make_array(mutable.freeze());
265 let values = cast_with_options(values.as_ref(), field.data_type(), cast_options)?;
266
267 let nulls = null_builder.build();
268 let array = if size == 0 && nulls.is_none() {
271 FixedSizeListArray::try_new_with_length(field.clone(), size, values, nulls, array.len())?
272 } else {
273 FixedSizeListArray::try_new(field.clone(), size, values, nulls)?
274 };
275 Ok(Arc::new(array))
276}
277
278pub(crate) fn cast_list_values<O: OffsetSizeTrait>(
280 array: &dyn Array,
281 to: &FieldRef,
282 cast_options: &CastOptions,
283) -> Result<ArrayRef, ArrowError> {
284 let list = array.as_list::<O>();
285 let values = cast_with_options(list.values(), to.data_type(), cast_options)?;
286 Ok(Arc::new(GenericListArray::<O>::try_new(
287 to.clone(),
288 list.offsets().clone(),
289 values,
290 list.nulls().cloned(),
291 )?))
292}
293
294pub(crate) fn cast_list_view_values<O: OffsetSizeTrait>(
296 array: &dyn Array,
297 to: &FieldRef,
298 cast_options: &CastOptions,
299) -> Result<ArrayRef, ArrowError> {
300 let list = array.as_list_view::<O>();
301 let values = cast_with_options(list.values(), to.data_type(), cast_options)?;
302 Ok(Arc::new(GenericListViewArray::<O>::try_new(
303 to.clone(),
304 list.offsets().clone(),
305 list.sizes().clone(),
306 values,
307 list.nulls().cloned(),
308 )?))
309}
310
311pub(crate) fn cast_list<I: OffsetSizeTrait, O: OffsetSizeTrait>(
313 array: &dyn Array,
314 field: &FieldRef,
315 cast_options: &CastOptions,
316) -> Result<ArrayRef, ArrowError> {
317 let list = array.as_list::<I>();
318 let values = list.values();
319 let offsets = list.offsets();
320 let nulls = list.nulls().cloned();
321
322 if offsets.last().as_usize() > O::MAX_OFFSET {
323 return Err(ArrowError::ComputeError(format!(
324 "Offset overflow when casting from {} to {}",
325 array.data_type(),
326 field.data_type()
327 )));
328 }
329
330 let values = cast_with_options(values, field.data_type(), cast_options)?;
332 let offsets: Vec<_> = offsets.iter().map(|x| O::usize_as(x.as_usize())).collect();
333
334 let offsets = unsafe { OffsetBuffer::new_unchecked(offsets.into()) };
336
337 Ok(Arc::new(GenericListArray::<O>::try_new(
338 field.clone(),
339 offsets,
340 values,
341 nulls,
342 )?))
343}
344
345pub(crate) fn cast_list_view_to_list<I, O>(
347 array: &dyn Array,
348 to: &FieldRef,
349 cast_options: &CastOptions,
350) -> Result<ArrayRef, ArrowError>
351where
352 I: OffsetSizeTrait,
353 O: ArrowPrimitiveType,
356 O::Native: OffsetSizeTrait,
357{
358 let list_view = array.as_list_view::<I>();
359 let list_view_offsets = list_view.offsets();
360 let sizes = list_view.sizes();
361
362 let mut take_indices: Vec<O::Native> = Vec::with_capacity(list_view.values().len());
363 let mut offsets: Vec<O::Native> = Vec::with_capacity(list_view.len() + 1);
364 use num_traits::Zero;
365 offsets.push(O::Native::zero());
366
367 for i in 0..list_view.len() {
368 if list_view.is_null(i) {
369 offsets.push(O::Native::usize_as(take_indices.len()));
370 continue;
371 }
372
373 let offset = list_view_offsets[i].as_usize();
374 let size = sizes[i].as_usize();
375
376 for value_index in offset..offset + size {
377 take_indices.push(O::Native::usize_as(value_index));
378 }
379
380 if take_indices.len() > O::Native::MAX_OFFSET {
383 return Err(ArrowError::ComputeError(format!(
384 "Offset overflow when casting from {} to {}",
385 array.data_type(),
386 to.data_type()
387 )));
388 }
389 offsets.push(O::Native::usize_as(take_indices.len()));
390 }
391
392 let take_indices = PrimitiveArray::<O>::from_iter_values(take_indices);
394 let values = arrow_select::take::take(list_view.values(), &take_indices, None)?;
395 let values = cast_with_options(&values, to.data_type(), cast_options)?;
396
397 Ok(Arc::new(GenericListArray::<O::Native>::try_new(
398 to.clone(),
399 OffsetBuffer::new(offsets.into()),
400 values,
401 list_view.nulls().cloned(),
402 )?))
403}
404
405pub(crate) fn cast_list_view<I: OffsetSizeTrait, O: OffsetSizeTrait>(
407 array: &dyn Array,
408 to_field: &FieldRef,
409 cast_options: &CastOptions,
410) -> Result<ArrayRef, ArrowError> {
411 let list_view = array.as_list_view::<I>();
412
413 let values = cast_with_options(list_view.values(), to_field.data_type(), cast_options)?;
415
416 let offsets = list_view
417 .offsets()
418 .iter()
419 .map(|offset| {
420 let offset = offset.as_usize();
421 if offset > O::MAX_OFFSET {
422 return Err(ArrowError::ComputeError(format!(
423 "Offset overflow when casting from {} to {}",
424 array.data_type(),
425 to_field.data_type()
426 )));
427 }
428 Ok(O::usize_as(offset))
429 })
430 .collect::<Result<Vec<O>, _>>()?;
431 let sizes = list_view
432 .sizes()
433 .iter()
434 .map(|size| {
435 let size = size.as_usize();
436 if size > O::MAX_OFFSET {
437 return Err(ArrowError::ComputeError(format!(
438 "Offset overflow when casting from {} to {}",
439 array.data_type(),
440 to_field.data_type()
441 )));
442 }
443 Ok(O::usize_as(size))
444 })
445 .collect::<Result<Vec<O>, _>>()?;
446 Ok(Arc::new(GenericListViewArray::<O>::try_new(
447 to_field.clone(),
448 offsets.into(),
449 sizes.into(),
450 values,
451 list_view.nulls().cloned(),
452 )?))
453}
454
455pub(crate) fn cast_list_to_list_view<I: OffsetSizeTrait, O: OffsetSizeTrait>(
457 array: &dyn Array,
458 to_field: &FieldRef,
459 cast_options: &CastOptions,
460) -> Result<ArrayRef, ArrowError> {
461 let list = array.as_list::<I>();
462 let (_field, offsets, values, nulls) = list.clone().into_parts();
463
464 let len = offsets.len() - 1;
465 let mut sizes = Vec::with_capacity(len);
466 let mut view_offsets = Vec::with_capacity(len);
467 for (i, offset) in offsets.iter().enumerate().take(len) {
468 let offset = offset.as_usize();
469 let size = offsets[i + 1].as_usize() - offset;
470
471 if offset > O::MAX_OFFSET || size > O::MAX_OFFSET {
472 return Err(ArrowError::ComputeError(format!(
473 "Offset overflow when casting from {} to {}",
474 array.data_type(),
475 to_field.data_type()
476 )));
477 }
478
479 view_offsets.push(O::usize_as(offset));
480 sizes.push(O::usize_as(size));
481 }
482 let values = cast_with_options(&values, to_field.data_type(), cast_options)?;
483 let array = GenericListViewArray::<O>::new(
484 to_field.clone(),
485 view_offsets.into(),
486 sizes.into(),
487 values,
488 nulls,
489 );
490 Ok(Arc::new(array))
491}