1mod binary_to;
4mod binview_to;
5mod boolean_to;
6mod decimal_to;
7mod dictionary_to;
8mod primitive_to;
9mod utf8_to;
10
11pub use binary_to::*;
12#[cfg(feature = "dtype-decimal")]
13pub use binview_to::binview_to_decimal;
14use binview_to::binview_to_primitive_dyn;
15pub use binview_to::utf8view_to_utf8;
16pub use boolean_to::*;
17pub use decimal_to::*;
18pub mod temporal;
19use arrow::array::*;
20use arrow::datatypes::*;
21use arrow::match_integer_type;
22use arrow::offset::{Offset, Offsets};
23use binview_to::{
24 binview_to_dictionary, utf8view_to_date32_dyn, utf8view_to_dictionary,
25 utf8view_to_naive_timestamp_dyn, view_to_binary,
26};
27use dictionary_to::*;
28use polars_error::{polars_bail, polars_ensure, polars_err, PolarsResult};
29use polars_utils::IdxSize;
30pub use primitive_to::*;
31use temporal::utf8view_to_timestamp;
32pub use utf8_to::*;
33
34#[derive(Clone, Copy, Debug, Default)]
36pub struct CastOptionsImpl {
37 pub wrapped: bool,
41 pub partial: bool,
44}
45
46impl CastOptionsImpl {
47 pub fn unchecked() -> Self {
48 Self {
49 wrapped: true,
50 partial: false,
51 }
52 }
53}
54
55impl CastOptionsImpl {
56 fn with_wrapped(&self, v: bool) -> Self {
57 let mut option = *self;
58 option.wrapped = v;
59 option
60 }
61}
62
63macro_rules! primitive_dyn {
64 ($from:expr, $expr:tt) => {{
65 let from = $from.as_any().downcast_ref().unwrap();
66 Ok(Box::new($expr(from)))
67 }};
68 ($from:expr, $expr:tt, $to:expr) => {{
69 let from = $from.as_any().downcast_ref().unwrap();
70 Ok(Box::new($expr(from, $to)))
71 }};
72 ($from:expr, $expr:tt, $from_t:expr, $to:expr) => {{
73 let from = $from.as_any().downcast_ref().unwrap();
74 Ok(Box::new($expr(from, $from_t, $to)))
75 }};
76 ($from:expr, $expr:tt, $arg1:expr, $arg2:expr, $arg3:expr) => {{
77 let from = $from.as_any().downcast_ref().unwrap();
78 Ok(Box::new($expr(from, $arg1, $arg2, $arg3)))
79 }};
80}
81
82fn cast_struct(
83 array: &StructArray,
84 to_type: &ArrowDataType,
85 options: CastOptionsImpl,
86) -> PolarsResult<StructArray> {
87 let values = array.values();
88 let fields = StructArray::get_fields(to_type);
89 let new_values = values
90 .iter()
91 .zip(fields)
92 .map(|(arr, field)| cast(arr.as_ref(), field.dtype(), options))
93 .collect::<PolarsResult<Vec<_>>>()?;
94
95 Ok(StructArray::new(
96 to_type.clone(),
97 array.len(),
98 new_values,
99 array.validity().cloned(),
100 ))
101}
102
103fn cast_list<O: Offset>(
104 array: &ListArray<O>,
105 to_type: &ArrowDataType,
106 options: CastOptionsImpl,
107) -> PolarsResult<ListArray<O>> {
108 let values = array.values();
109 let new_values = cast(
110 values.as_ref(),
111 ListArray::<O>::get_child_type(to_type),
112 options,
113 )?;
114
115 Ok(ListArray::<O>::new(
116 to_type.clone(),
117 array.offsets().clone(),
118 new_values,
119 array.validity().cloned(),
120 ))
121}
122
123fn cast_list_to_large_list(array: &ListArray<i32>, to_type: &ArrowDataType) -> ListArray<i64> {
124 let offsets = array.offsets().into();
125
126 ListArray::<i64>::new(
127 to_type.clone(),
128 offsets,
129 array.values().clone(),
130 array.validity().cloned(),
131 )
132}
133
134fn cast_large_to_list(array: &ListArray<i64>, to_type: &ArrowDataType) -> ListArray<i32> {
135 let offsets = array.offsets().try_into().expect("Convertme to error");
136
137 ListArray::<i32>::new(
138 to_type.clone(),
139 offsets,
140 array.values().clone(),
141 array.validity().cloned(),
142 )
143}
144
145fn cast_fixed_size_list_to_list<O: Offset>(
146 fixed: &FixedSizeListArray,
147 to_type: &ArrowDataType,
148 options: CastOptionsImpl,
149) -> PolarsResult<ListArray<O>> {
150 let new_values = cast(
151 fixed.values().as_ref(),
152 ListArray::<O>::get_child_type(to_type),
153 options,
154 )?;
155
156 let offsets = (0..=fixed.len())
157 .map(|ix| O::from_as_usize(ix * fixed.size()))
158 .collect::<Vec<_>>();
159 let offsets = unsafe { Offsets::new_unchecked(offsets) };
161
162 Ok(ListArray::<O>::new(
163 to_type.clone(),
164 offsets.into(),
165 new_values,
166 fixed.validity().cloned(),
167 ))
168}
169
170fn cast_list_to_fixed_size_list<O: Offset>(
171 list: &ListArray<O>,
172 inner: &Field,
173 size: usize,
174 options: CastOptionsImpl,
175) -> PolarsResult<FixedSizeListArray> {
176 let null_cnt = list.null_count();
177 let new_values = if null_cnt == 0 {
178 let start_offset = list.offsets().first().to_usize();
179 let offsets = list.offsets().buffer();
180
181 let mut is_valid = true;
182 for (i, offset) in offsets.iter().enumerate() {
183 is_valid &= offset.to_usize() == start_offset + i * size;
184 }
185
186 polars_ensure!(is_valid, ComputeError: "not all elements have the specified width {size}");
187
188 let sliced_values = list
189 .values()
190 .sliced(start_offset, list.offsets().range().to_usize());
191 cast(sliced_values.as_ref(), inner.dtype(), options)?
192 } else {
193 let offsets = list.offsets().as_slice();
194 let mut expected_offset = unsafe { *offsets.get_unchecked(0) } + O::from_as_usize(size);
197 for i in 1..=list.len() {
198 let current_offset = unsafe { *offsets.get_unchecked(i) };
200 if list.is_null(i - 1) {
201 expected_offset = current_offset + O::from_as_usize(size);
202 } else {
203 polars_ensure!(current_offset == expected_offset, ComputeError:
204 "not all elements have the specified width {size}");
205 expected_offset += O::from_as_usize(size);
206 }
207 }
208
209 let mut indices =
211 MutablePrimitiveArray::<IdxSize>::with_capacity(list.values().len() + null_cnt * size);
212 for i in 0..list.len() {
213 if list.is_null(i) {
214 indices.extend_constant(size, None)
215 } else {
216 let current_offset = unsafe { *offsets.get_unchecked(i) };
218 for j in 0..size {
219 indices.push(Some(
220 (current_offset + O::from_as_usize(j)).to_usize() as IdxSize
221 ));
222 }
223 }
224 }
225 let take_values =
226 unsafe { crate::gather::take_unchecked(list.values().as_ref(), &indices.freeze()) };
227
228 cast(take_values.as_ref(), inner.dtype(), options)?
229 };
230
231 FixedSizeListArray::try_new(
232 ArrowDataType::FixedSizeList(Box::new(inner.clone()), size),
233 list.len(),
234 new_values,
235 list.validity().cloned(),
236 )
237 .map_err(|_| polars_err!(ComputeError: "not all elements have the specified width {size}"))
238}
239
240pub fn cast_default(array: &dyn Array, to_type: &ArrowDataType) -> PolarsResult<Box<dyn Array>> {
241 cast(array, to_type, Default::default())
242}
243
244pub fn cast_unchecked(array: &dyn Array, to_type: &ArrowDataType) -> PolarsResult<Box<dyn Array>> {
245 cast(array, to_type, CastOptionsImpl::unchecked())
246}
247
248pub fn cast(
274 array: &dyn Array,
275 to_type: &ArrowDataType,
276 options: CastOptionsImpl,
277) -> PolarsResult<Box<dyn Array>> {
278 use ArrowDataType::*;
279 let from_type = array.dtype();
280
281 if from_type == to_type {
283 return Ok(clone(array));
284 }
285
286 let as_options = options.with_wrapped(true);
287 match (from_type, to_type) {
288 (Null, _) | (_, Null) => Ok(new_null_array(to_type.clone(), array.len())),
289 (Struct(from_fd), Struct(to_fd)) => {
290 polars_ensure!(from_fd.len() == to_fd.len(), InvalidOperation: "Cannot cast struct with different number of fields.");
291 cast_struct(array.as_any().downcast_ref().unwrap(), to_type, options).map(|x| x.boxed())
292 },
293 (Struct(_), _) | (_, Struct(_)) => polars_bail!(InvalidOperation:
294 "Cannot cast from struct to other types"
295 ),
296 (Dictionary(index_type, ..), _) => match_integer_type!(index_type, |$T| {
297 dictionary_cast_dyn::<$T>(array, to_type, options)
298 }),
299 (_, Dictionary(index_type, value_type, _)) => match_integer_type!(index_type, |$T| {
300 cast_to_dictionary::<$T>(array, value_type, options)
301 }),
302 (LargeList(_), FixedSizeList(inner, size)) => cast_list_to_fixed_size_list::<i64>(
311 array.as_any().downcast_ref().unwrap(),
312 inner.as_ref(),
313 *size,
314 options,
315 )
316 .map(|x| x.boxed()),
317 (FixedSizeList(_, _), List(_)) => cast_fixed_size_list_to_list::<i32>(
318 array.as_any().downcast_ref().unwrap(),
319 to_type,
320 options,
321 )
322 .map(|x| x.boxed()),
323 (FixedSizeList(_, _), LargeList(_)) => cast_fixed_size_list_to_list::<i64>(
324 array.as_any().downcast_ref().unwrap(),
325 to_type,
326 options,
327 )
328 .map(|x| x.boxed()),
329 (BinaryView, _) => match to_type {
330 Utf8View => array
331 .as_any()
332 .downcast_ref::<BinaryViewArray>()
333 .unwrap()
334 .to_utf8view()
335 .map(|arr| arr.boxed()),
336 LargeBinary => Ok(binview_to::view_to_binary::<i64>(
337 array.as_any().downcast_ref().unwrap(),
338 )
339 .boxed()),
340 LargeList(inner) if matches!(inner.dtype, ArrowDataType::UInt8) => {
341 let bin_array = view_to_binary::<i64>(array.as_any().downcast_ref().unwrap());
342 Ok(binary_to_list(&bin_array, to_type.clone()).boxed())
343 },
344 _ => polars_bail!(InvalidOperation:
345 "casting from {from_type:?} to {to_type:?} not supported",
346 ),
347 },
348 (LargeList(_), LargeList(_)) => {
349 cast_list::<i64>(array.as_any().downcast_ref().unwrap(), to_type, options)
350 .map(|x| x.boxed())
351 },
352 (List(lhs), LargeList(rhs)) if lhs == rhs => {
353 Ok(cast_list_to_large_list(array.as_any().downcast_ref().unwrap(), to_type).boxed())
354 },
355 (LargeList(lhs), List(rhs)) if lhs == rhs => {
356 Ok(cast_large_to_list(array.as_any().downcast_ref().unwrap(), to_type).boxed())
357 },
358
359 (_, List(to)) => {
360 let values = cast(array, &to.dtype, options)?;
362 let offsets = (0..=array.len() as i32).collect::<Vec<_>>();
364 let offsets = unsafe { Offsets::new_unchecked(offsets) };
366
367 let list_array = ListArray::<i32>::new(to_type.clone(), offsets.into(), values, None);
368
369 Ok(Box::new(list_array))
370 },
371
372 (_, LargeList(to)) if from_type != &LargeBinary => {
373 let values = cast(array, &to.dtype, options)?;
375 let offsets = (0..=array.len() as i64).collect::<Vec<_>>();
377 let offsets = unsafe { Offsets::new_unchecked(offsets) };
379
380 let list_array = ListArray::<i64>::new(
381 to_type.clone(),
382 offsets.into(),
383 values,
384 array.validity().cloned(),
385 );
386
387 Ok(Box::new(list_array))
388 },
389
390 (Utf8View, _) => {
391 let arr = array.as_any().downcast_ref::<Utf8ViewArray>().unwrap();
392
393 match to_type {
394 BinaryView => Ok(arr.to_binview().boxed()),
395 LargeUtf8 => Ok(binview_to::utf8view_to_utf8::<i64>(arr).boxed()),
396 UInt8 => binview_to_primitive_dyn::<u8>(&arr.to_binview(), to_type, options),
397 UInt16 => binview_to_primitive_dyn::<u16>(&arr.to_binview(), to_type, options),
398 UInt32 => binview_to_primitive_dyn::<u32>(&arr.to_binview(), to_type, options),
399 UInt64 => binview_to_primitive_dyn::<u64>(&arr.to_binview(), to_type, options),
400 Int8 => binview_to_primitive_dyn::<i8>(&arr.to_binview(), to_type, options),
401 Int16 => binview_to_primitive_dyn::<i16>(&arr.to_binview(), to_type, options),
402 Int32 => binview_to_primitive_dyn::<i32>(&arr.to_binview(), to_type, options),
403 Int64 => binview_to_primitive_dyn::<i64>(&arr.to_binview(), to_type, options),
404 #[cfg(feature = "dtype-i128")]
405 Int128 => binview_to_primitive_dyn::<i128>(&arr.to_binview(), to_type, options),
406 Float32 => binview_to_primitive_dyn::<f32>(&arr.to_binview(), to_type, options),
407 Float64 => binview_to_primitive_dyn::<f64>(&arr.to_binview(), to_type, options),
408 Timestamp(time_unit, None) => {
409 utf8view_to_naive_timestamp_dyn(array, time_unit.to_owned())
410 },
411 Timestamp(time_unit, Some(time_zone)) => utf8view_to_timestamp(
412 array.as_any().downcast_ref().unwrap(),
413 RFC3339,
414 time_zone.clone(),
415 time_unit.to_owned(),
416 )
417 .map(|arr| arr.boxed()),
418 Date32 => utf8view_to_date32_dyn(array),
419 #[cfg(feature = "dtype-decimal")]
420 Decimal(precision, scale) => {
421 Ok(binview_to_decimal(&arr.to_binview(), Some(*precision), *scale).to_boxed())
422 },
423 _ => polars_bail!(InvalidOperation:
424 "casting from {from_type:?} to {to_type:?} not supported",
425 ),
426 }
427 },
428
429 (_, Boolean) => match from_type {
430 UInt8 => primitive_to_boolean_dyn::<u8>(array, to_type.clone()),
431 UInt16 => primitive_to_boolean_dyn::<u16>(array, to_type.clone()),
432 UInt32 => primitive_to_boolean_dyn::<u32>(array, to_type.clone()),
433 UInt64 => primitive_to_boolean_dyn::<u64>(array, to_type.clone()),
434 Int8 => primitive_to_boolean_dyn::<i8>(array, to_type.clone()),
435 Int16 => primitive_to_boolean_dyn::<i16>(array, to_type.clone()),
436 Int32 => primitive_to_boolean_dyn::<i32>(array, to_type.clone()),
437 Int64 => primitive_to_boolean_dyn::<i64>(array, to_type.clone()),
438 #[cfg(feature = "dtype-i128")]
439 Int128 => primitive_to_boolean_dyn::<i128>(array, to_type.clone()),
440 Float32 => primitive_to_boolean_dyn::<f32>(array, to_type.clone()),
441 Float64 => primitive_to_boolean_dyn::<f64>(array, to_type.clone()),
442 Decimal(_, _) => primitive_to_boolean_dyn::<i128>(array, to_type.clone()),
443 _ => polars_bail!(InvalidOperation:
444 "casting from {from_type:?} to {to_type:?} not supported",
445 ),
446 },
447 (Boolean, _) => match to_type {
448 UInt8 => boolean_to_primitive_dyn::<u8>(array),
449 UInt16 => boolean_to_primitive_dyn::<u16>(array),
450 UInt32 => boolean_to_primitive_dyn::<u32>(array),
451 UInt64 => boolean_to_primitive_dyn::<u64>(array),
452 Int8 => boolean_to_primitive_dyn::<i8>(array),
453 Int16 => boolean_to_primitive_dyn::<i16>(array),
454 Int32 => boolean_to_primitive_dyn::<i32>(array),
455 Int64 => boolean_to_primitive_dyn::<i64>(array),
456 #[cfg(feature = "dtype-i128")]
457 Int128 => boolean_to_primitive_dyn::<i128>(array),
458 Float32 => boolean_to_primitive_dyn::<f32>(array),
459 Float64 => boolean_to_primitive_dyn::<f64>(array),
460 Utf8View => boolean_to_utf8view_dyn(array),
461 BinaryView => boolean_to_binaryview_dyn(array),
462 _ => polars_bail!(InvalidOperation:
463 "casting from {from_type:?} to {to_type:?} not supported",
464 ),
465 },
466 (_, BinaryView) => from_to_binview(array, from_type, to_type).map(|arr| arr.boxed()),
467 (_, Utf8View) => match from_type {
468 LargeUtf8 => Ok(utf8_to_utf8view(
469 array.as_any().downcast_ref::<Utf8Array<i64>>().unwrap(),
470 )
471 .boxed()),
472 Utf8 => Ok(
473 utf8_to_utf8view(array.as_any().downcast_ref::<Utf8Array<i32>>().unwrap()).boxed(),
474 ),
475 #[cfg(feature = "dtype-decimal")]
476 Decimal(_, _) => Ok(decimal_to_utf8view_dyn(array).boxed()),
477 _ => from_to_binview(array, from_type, to_type)
478 .map(|arr| unsafe { arr.to_utf8view_unchecked() }.boxed()),
479 },
480 (Utf8, _) => match to_type {
481 LargeUtf8 => Ok(Box::new(utf8_to_large_utf8(
482 array.as_any().downcast_ref().unwrap(),
483 ))),
484 _ => polars_bail!(InvalidOperation:
485 "casting from {from_type:?} to {to_type:?} not supported",
486 ),
487 },
488 (LargeUtf8, _) => match to_type {
489 LargeBinary => Ok(utf8_to_binary::<i64>(
490 array.as_any().downcast_ref().unwrap(),
491 to_type.clone(),
492 )
493 .boxed()),
494 _ => polars_bail!(InvalidOperation:
495 "casting from {from_type:?} to {to_type:?} not supported",
496 ),
497 },
498 (_, LargeUtf8) => match from_type {
499 UInt8 => primitive_to_utf8_dyn::<u8, i64>(array),
500 LargeBinary => {
501 binary_to_utf8::<i64>(array.as_any().downcast_ref().unwrap(), to_type.clone())
502 .map(|x| x.boxed())
503 },
504 _ => polars_bail!(InvalidOperation:
505 "casting from {from_type:?} to {to_type:?} not supported",
506 ),
507 },
508
509 (Binary, _) => match to_type {
510 LargeBinary => Ok(Box::new(binary_to_large_binary(
511 array.as_any().downcast_ref().unwrap(),
512 to_type.clone(),
513 ))),
514 _ => polars_bail!(InvalidOperation:
515 "casting from {from_type:?} to {to_type:?} not supported",
516 ),
517 },
518
519 (LargeBinary, _) => match to_type {
520 UInt8 => binary_to_primitive_dyn::<i64, u8>(array, to_type, options),
521 UInt16 => binary_to_primitive_dyn::<i64, u16>(array, to_type, options),
522 UInt32 => binary_to_primitive_dyn::<i64, u32>(array, to_type, options),
523 UInt64 => binary_to_primitive_dyn::<i64, u64>(array, to_type, options),
524 Int8 => binary_to_primitive_dyn::<i64, i8>(array, to_type, options),
525 Int16 => binary_to_primitive_dyn::<i64, i16>(array, to_type, options),
526 Int32 => binary_to_primitive_dyn::<i64, i32>(array, to_type, options),
527 Int64 => binary_to_primitive_dyn::<i64, i64>(array, to_type, options),
528 #[cfg(feature = "dtype-i128")]
529 Int128 => binary_to_primitive_dyn::<i64, i128>(array, to_type, options),
530 Float32 => binary_to_primitive_dyn::<i64, f32>(array, to_type, options),
531 Float64 => binary_to_primitive_dyn::<i64, f64>(array, to_type, options),
532 Binary => {
533 binary_large_to_binary(array.as_any().downcast_ref().unwrap(), to_type.clone())
534 .map(|x| x.boxed())
535 },
536 LargeUtf8 => {
537 binary_to_utf8::<i64>(array.as_any().downcast_ref().unwrap(), to_type.clone())
538 .map(|x| x.boxed())
539 },
540 _ => polars_bail!(InvalidOperation:
541 "casting from {from_type:?} to {to_type:?} not supported",
542 ),
543 },
544 (FixedSizeBinary(_), _) => match to_type {
545 Binary => Ok(fixed_size_binary_binary::<i32>(
546 array.as_any().downcast_ref().unwrap(),
547 to_type.clone(),
548 )
549 .boxed()),
550 LargeBinary => Ok(fixed_size_binary_binary::<i64>(
551 array.as_any().downcast_ref().unwrap(),
552 to_type.clone(),
553 )
554 .boxed()),
555 _ => polars_bail!(InvalidOperation:
556 "casting from {from_type:?} to {to_type:?} not supported",
557 ),
558 },
559 (UInt8, UInt16) => primitive_to_primitive_dyn::<u8, u16>(array, to_type, as_options),
561 (UInt8, UInt32) => primitive_to_primitive_dyn::<u8, u32>(array, to_type, as_options),
562 (UInt8, UInt64) => primitive_to_primitive_dyn::<u8, u64>(array, to_type, as_options),
563 (UInt8, Int8) => primitive_to_primitive_dyn::<u8, i8>(array, to_type, options),
564 (UInt8, Int16) => primitive_to_primitive_dyn::<u8, i16>(array, to_type, options),
565 (UInt8, Int32) => primitive_to_primitive_dyn::<u8, i32>(array, to_type, options),
566 (UInt8, Int64) => primitive_to_primitive_dyn::<u8, i64>(array, to_type, options),
567 #[cfg(feature = "dtype-i128")]
568 (UInt8, Int128) => primitive_to_primitive_dyn::<u8, i128>(array, to_type, options),
569 (UInt8, Float32) => primitive_to_primitive_dyn::<u8, f32>(array, to_type, as_options),
570 (UInt8, Float64) => primitive_to_primitive_dyn::<u8, f64>(array, to_type, as_options),
571 (UInt8, Decimal(p, s)) => integer_to_decimal_dyn::<u8>(array, *p, *s),
572
573 (UInt16, UInt8) => primitive_to_primitive_dyn::<u16, u8>(array, to_type, options),
574 (UInt16, UInt32) => primitive_to_primitive_dyn::<u16, u32>(array, to_type, as_options),
575 (UInt16, UInt64) => primitive_to_primitive_dyn::<u16, u64>(array, to_type, as_options),
576 (UInt16, Int8) => primitive_to_primitive_dyn::<u16, i8>(array, to_type, options),
577 (UInt16, Int16) => primitive_to_primitive_dyn::<u16, i16>(array, to_type, options),
578 (UInt16, Int32) => primitive_to_primitive_dyn::<u16, i32>(array, to_type, options),
579 (UInt16, Int64) => primitive_to_primitive_dyn::<u16, i64>(array, to_type, options),
580 #[cfg(feature = "dtype-i128")]
581 (UInt16, Int128) => primitive_to_primitive_dyn::<u16, i128>(array, to_type, options),
582 (UInt16, Float32) => primitive_to_primitive_dyn::<u16, f32>(array, to_type, as_options),
583 (UInt16, Float64) => primitive_to_primitive_dyn::<u16, f64>(array, to_type, as_options),
584 (UInt16, Decimal(p, s)) => integer_to_decimal_dyn::<u16>(array, *p, *s),
585
586 (UInt32, UInt8) => primitive_to_primitive_dyn::<u32, u8>(array, to_type, options),
587 (UInt32, UInt16) => primitive_to_primitive_dyn::<u32, u16>(array, to_type, options),
588 (UInt32, UInt64) => primitive_to_primitive_dyn::<u32, u64>(array, to_type, as_options),
589 (UInt32, Int8) => primitive_to_primitive_dyn::<u32, i8>(array, to_type, options),
590 (UInt32, Int16) => primitive_to_primitive_dyn::<u32, i16>(array, to_type, options),
591 (UInt32, Int32) => primitive_to_primitive_dyn::<u32, i32>(array, to_type, options),
592 (UInt32, Int64) => primitive_to_primitive_dyn::<u32, i64>(array, to_type, options),
593 #[cfg(feature = "dtype-i128")]
594 (UInt32, Int128) => primitive_to_primitive_dyn::<u32, i128>(array, to_type, options),
595 (UInt32, Float32) => primitive_to_primitive_dyn::<u32, f32>(array, to_type, as_options),
596 (UInt32, Float64) => primitive_to_primitive_dyn::<u32, f64>(array, to_type, as_options),
597 (UInt32, Decimal(p, s)) => integer_to_decimal_dyn::<u32>(array, *p, *s),
598
599 (UInt64, UInt8) => primitive_to_primitive_dyn::<u64, u8>(array, to_type, options),
600 (UInt64, UInt16) => primitive_to_primitive_dyn::<u64, u16>(array, to_type, options),
601 (UInt64, UInt32) => primitive_to_primitive_dyn::<u64, u32>(array, to_type, options),
602 (UInt64, Int8) => primitive_to_primitive_dyn::<u64, i8>(array, to_type, options),
603 (UInt64, Int16) => primitive_to_primitive_dyn::<u64, i16>(array, to_type, options),
604 (UInt64, Int32) => primitive_to_primitive_dyn::<u64, i32>(array, to_type, options),
605 (UInt64, Int64) => primitive_to_primitive_dyn::<u64, i64>(array, to_type, options),
606 #[cfg(feature = "dtype-i128")]
607 (UInt64, Int128) => primitive_to_primitive_dyn::<u64, i128>(array, to_type, options),
608 (UInt64, Float32) => primitive_to_primitive_dyn::<u64, f32>(array, to_type, as_options),
609 (UInt64, Float64) => primitive_to_primitive_dyn::<u64, f64>(array, to_type, as_options),
610 (UInt64, Decimal(p, s)) => integer_to_decimal_dyn::<u64>(array, *p, *s),
611
612 (Int8, UInt8) => primitive_to_primitive_dyn::<i8, u8>(array, to_type, options),
613 (Int8, UInt16) => primitive_to_primitive_dyn::<i8, u16>(array, to_type, options),
614 (Int8, UInt32) => primitive_to_primitive_dyn::<i8, u32>(array, to_type, options),
615 (Int8, UInt64) => primitive_to_primitive_dyn::<i8, u64>(array, to_type, options),
616 (Int8, Int16) => primitive_to_primitive_dyn::<i8, i16>(array, to_type, as_options),
617 (Int8, Int32) => primitive_to_primitive_dyn::<i8, i32>(array, to_type, as_options),
618 (Int8, Int64) => primitive_to_primitive_dyn::<i8, i64>(array, to_type, as_options),
619 #[cfg(feature = "dtype-i128")]
620 (Int8, Int128) => primitive_to_primitive_dyn::<i8, i128>(array, to_type, as_options),
621 (Int8, Float32) => primitive_to_primitive_dyn::<i8, f32>(array, to_type, as_options),
622 (Int8, Float64) => primitive_to_primitive_dyn::<i8, f64>(array, to_type, as_options),
623 (Int8, Decimal(p, s)) => integer_to_decimal_dyn::<i8>(array, *p, *s),
624
625 (Int16, UInt8) => primitive_to_primitive_dyn::<i16, u8>(array, to_type, options),
626 (Int16, UInt16) => primitive_to_primitive_dyn::<i16, u16>(array, to_type, options),
627 (Int16, UInt32) => primitive_to_primitive_dyn::<i16, u32>(array, to_type, options),
628 (Int16, UInt64) => primitive_to_primitive_dyn::<i16, u64>(array, to_type, options),
629 (Int16, Int8) => primitive_to_primitive_dyn::<i16, i8>(array, to_type, options),
630 (Int16, Int32) => primitive_to_primitive_dyn::<i16, i32>(array, to_type, as_options),
631 (Int16, Int64) => primitive_to_primitive_dyn::<i16, i64>(array, to_type, as_options),
632 #[cfg(feature = "dtype-i128")]
633 (Int16, Int128) => primitive_to_primitive_dyn::<i16, i128>(array, to_type, as_options),
634 (Int16, Float32) => primitive_to_primitive_dyn::<i16, f32>(array, to_type, as_options),
635 (Int16, Float64) => primitive_to_primitive_dyn::<i16, f64>(array, to_type, as_options),
636 (Int16, Decimal(p, s)) => integer_to_decimal_dyn::<i16>(array, *p, *s),
637
638 (Int32, UInt8) => primitive_to_primitive_dyn::<i32, u8>(array, to_type, options),
639 (Int32, UInt16) => primitive_to_primitive_dyn::<i32, u16>(array, to_type, options),
640 (Int32, UInt32) => primitive_to_primitive_dyn::<i32, u32>(array, to_type, options),
641 (Int32, UInt64) => primitive_to_primitive_dyn::<i32, u64>(array, to_type, options),
642 (Int32, Int8) => primitive_to_primitive_dyn::<i32, i8>(array, to_type, options),
643 (Int32, Int16) => primitive_to_primitive_dyn::<i32, i16>(array, to_type, options),
644 (Int32, Int64) => primitive_to_primitive_dyn::<i32, i64>(array, to_type, as_options),
645 #[cfg(feature = "dtype-i128")]
646 (Int32, Int128) => primitive_to_primitive_dyn::<i32, i128>(array, to_type, as_options),
647 (Int32, Float32) => primitive_to_primitive_dyn::<i32, f32>(array, to_type, as_options),
648 (Int32, Float64) => primitive_to_primitive_dyn::<i32, f64>(array, to_type, as_options),
649 (Int32, Decimal(p, s)) => integer_to_decimal_dyn::<i32>(array, *p, *s),
650
651 (Int64, UInt8) => primitive_to_primitive_dyn::<i64, u8>(array, to_type, options),
652 (Int64, UInt16) => primitive_to_primitive_dyn::<i64, u16>(array, to_type, options),
653 (Int64, UInt32) => primitive_to_primitive_dyn::<i64, u32>(array, to_type, options),
654 (Int64, UInt64) => primitive_to_primitive_dyn::<i64, u64>(array, to_type, options),
655 (Int64, Int8) => primitive_to_primitive_dyn::<i64, i8>(array, to_type, options),
656 (Int64, Int16) => primitive_to_primitive_dyn::<i64, i16>(array, to_type, options),
657 (Int64, Int32) => primitive_to_primitive_dyn::<i64, i32>(array, to_type, options),
658 #[cfg(feature = "dtype-i128")]
659 (Int64, Int128) => primitive_to_primitive_dyn::<i64, i128>(array, to_type, options),
660 (Int64, Float32) => primitive_to_primitive_dyn::<i64, f32>(array, to_type, options),
661 (Int64, Float64) => primitive_to_primitive_dyn::<i64, f64>(array, to_type, as_options),
662 (Int64, Decimal(p, s)) => integer_to_decimal_dyn::<i64>(array, *p, *s),
663
664 #[cfg(feature = "dtype-i128")]
665 (Int128, UInt8) => primitive_to_primitive_dyn::<i128, u8>(array, to_type, options),
666 #[cfg(feature = "dtype-i128")]
667 (Int128, UInt16) => primitive_to_primitive_dyn::<i128, u16>(array, to_type, options),
668 #[cfg(feature = "dtype-i128")]
669 (Int128, UInt32) => primitive_to_primitive_dyn::<i128, u32>(array, to_type, options),
670 #[cfg(feature = "dtype-i128")]
671 (Int128, UInt64) => primitive_to_primitive_dyn::<i128, u64>(array, to_type, options),
672 #[cfg(feature = "dtype-i128")]
673 (Int128, Int8) => primitive_to_primitive_dyn::<i128, i8>(array, to_type, options),
674 #[cfg(feature = "dtype-i128")]
675 (Int128, Int16) => primitive_to_primitive_dyn::<i128, i16>(array, to_type, options),
676 #[cfg(feature = "dtype-i128")]
677 (Int128, Int32) => primitive_to_primitive_dyn::<i128, i32>(array, to_type, options),
678 #[cfg(feature = "dtype-i128")]
679 (Int128, Int64) => primitive_to_primitive_dyn::<i128, i64>(array, to_type, options),
680 #[cfg(feature = "dtype-i128")]
681 (Int128, Float32) => primitive_to_primitive_dyn::<i128, f32>(array, to_type, options),
682 #[cfg(feature = "dtype-i128")]
683 (Int128, Float64) => primitive_to_primitive_dyn::<i128, f64>(array, to_type, as_options),
684 #[cfg(feature = "dtype-i128")]
685 (Int128, Decimal(p, s)) => integer_to_decimal_dyn::<i128>(array, *p, *s),
686
687 (Float16, Float32) => {
688 let from = array.as_any().downcast_ref().unwrap();
689 Ok(f16_to_f32(from).boxed())
690 },
691
692 (Float32, UInt8) => primitive_to_primitive_dyn::<f32, u8>(array, to_type, options),
693 (Float32, UInt16) => primitive_to_primitive_dyn::<f32, u16>(array, to_type, options),
694 (Float32, UInt32) => primitive_to_primitive_dyn::<f32, u32>(array, to_type, options),
695 (Float32, UInt64) => primitive_to_primitive_dyn::<f32, u64>(array, to_type, options),
696 (Float32, Int8) => primitive_to_primitive_dyn::<f32, i8>(array, to_type, options),
697 (Float32, Int16) => primitive_to_primitive_dyn::<f32, i16>(array, to_type, options),
698 (Float32, Int32) => primitive_to_primitive_dyn::<f32, i32>(array, to_type, options),
699 (Float32, Int64) => primitive_to_primitive_dyn::<f32, i64>(array, to_type, options),
700 (Float32, Int128) => primitive_to_primitive_dyn::<f32, i128>(array, to_type, options),
701 (Float32, Float64) => primitive_to_primitive_dyn::<f32, f64>(array, to_type, as_options),
702 (Float32, Decimal(p, s)) => float_to_decimal_dyn::<f32>(array, *p, *s),
703
704 (Float64, UInt8) => primitive_to_primitive_dyn::<f64, u8>(array, to_type, options),
705 (Float64, UInt16) => primitive_to_primitive_dyn::<f64, u16>(array, to_type, options),
706 (Float64, UInt32) => primitive_to_primitive_dyn::<f64, u32>(array, to_type, options),
707 (Float64, UInt64) => primitive_to_primitive_dyn::<f64, u64>(array, to_type, options),
708 (Float64, Int8) => primitive_to_primitive_dyn::<f64, i8>(array, to_type, options),
709 (Float64, Int16) => primitive_to_primitive_dyn::<f64, i16>(array, to_type, options),
710 (Float64, Int32) => primitive_to_primitive_dyn::<f64, i32>(array, to_type, options),
711 (Float64, Int64) => primitive_to_primitive_dyn::<f64, i64>(array, to_type, options),
712 (Float64, Int128) => primitive_to_primitive_dyn::<f64, i128>(array, to_type, options),
713 (Float64, Float32) => primitive_to_primitive_dyn::<f64, f32>(array, to_type, options),
714 (Float64, Decimal(p, s)) => float_to_decimal_dyn::<f64>(array, *p, *s),
715
716 (Decimal(_, _), UInt8) => decimal_to_integer_dyn::<u8>(array),
717 (Decimal(_, _), UInt16) => decimal_to_integer_dyn::<u16>(array),
718 (Decimal(_, _), UInt32) => decimal_to_integer_dyn::<u32>(array),
719 (Decimal(_, _), UInt64) => decimal_to_integer_dyn::<u64>(array),
720 (Decimal(_, _), Int8) => decimal_to_integer_dyn::<i8>(array),
721 (Decimal(_, _), Int16) => decimal_to_integer_dyn::<i16>(array),
722 (Decimal(_, _), Int32) => decimal_to_integer_dyn::<i32>(array),
723 (Decimal(_, _), Int64) => decimal_to_integer_dyn::<i64>(array),
724 (Decimal(_, _), Int128) => decimal_to_integer_dyn::<i128>(array),
725 (Decimal(_, _), Float32) => decimal_to_float_dyn::<f32>(array),
726 (Decimal(_, _), Float64) => decimal_to_float_dyn::<f64>(array),
727 (Decimal(_, _), Decimal(to_p, to_s)) => decimal_to_decimal_dyn(array, *to_p, *to_s),
728 (Int32, Date32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
732 (Int32, Time32(TimeUnit::Second)) => primitive_dyn!(array, int32_to_time32s),
733 (Int32, Time32(TimeUnit::Millisecond)) => primitive_dyn!(array, int32_to_time32ms),
734 (Date32, Int32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
736 (Date32, Int64) => primitive_to_primitive_dyn::<i32, i64>(array, to_type, options),
737 (Time32(_), Int32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
738 (Int64, Date64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
739 (Int64, Time64(TimeUnit::Microsecond)) => primitive_dyn!(array, int64_to_time64us),
741 (Int64, Time64(TimeUnit::Nanosecond)) => primitive_dyn!(array, int64_to_time64ns),
742
743 (Date64, Int32) => primitive_to_primitive_dyn::<i64, i32>(array, to_type, options),
744 (Date64, Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
745 (Time64(_), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
746 (Date32, Date64) => primitive_dyn!(array, date32_to_date64),
747 (Date64, Date32) => primitive_dyn!(array, date64_to_date32),
748 (Time32(TimeUnit::Second), Time32(TimeUnit::Millisecond)) => {
749 primitive_dyn!(array, time32s_to_time32ms)
750 },
751 (Time32(TimeUnit::Millisecond), Time32(TimeUnit::Second)) => {
752 primitive_dyn!(array, time32ms_to_time32s)
753 },
754 (Time32(from_unit), Time64(to_unit)) => {
755 primitive_dyn!(array, time32_to_time64, *from_unit, *to_unit)
756 },
757 (Time64(TimeUnit::Microsecond), Time64(TimeUnit::Nanosecond)) => {
758 primitive_dyn!(array, time64us_to_time64ns)
759 },
760 (Time64(TimeUnit::Nanosecond), Time64(TimeUnit::Microsecond)) => {
761 primitive_dyn!(array, time64ns_to_time64us)
762 },
763 (Time64(from_unit), Time32(to_unit)) => {
764 primitive_dyn!(array, time64_to_time32, *from_unit, *to_unit)
765 },
766 (Timestamp(_, _), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
767 (Int64, Timestamp(_, _)) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
768 (Timestamp(from_unit, _), Timestamp(to_unit, tz)) => {
769 primitive_dyn!(array, timestamp_to_timestamp, *from_unit, *to_unit, tz)
770 },
771 (Timestamp(from_unit, _), Date32) => primitive_dyn!(array, timestamp_to_date32, *from_unit),
772 (Timestamp(from_unit, _), Date64) => primitive_dyn!(array, timestamp_to_date64, *from_unit),
773
774 (Int64, Duration(_)) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
775 (Duration(_), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
776
777 _ => polars_bail!(InvalidOperation:
785 "casting from {from_type:?} to {to_type:?} not supported",
786 ),
787 }
788}
789
790fn cast_to_dictionary<K: DictionaryKey>(
795 array: &dyn Array,
796 dict_value_type: &ArrowDataType,
797 options: CastOptionsImpl,
798) -> PolarsResult<Box<dyn Array>> {
799 let array = cast(array, dict_value_type, options)?;
800 let array = array.as_ref();
801 match *dict_value_type {
802 ArrowDataType::Int8 => primitive_to_dictionary_dyn::<i8, K>(array),
803 ArrowDataType::Int16 => primitive_to_dictionary_dyn::<i16, K>(array),
804 ArrowDataType::Int32 => primitive_to_dictionary_dyn::<i32, K>(array),
805 ArrowDataType::Int64 => primitive_to_dictionary_dyn::<i64, K>(array),
806 ArrowDataType::UInt8 => primitive_to_dictionary_dyn::<u8, K>(array),
807 ArrowDataType::UInt16 => primitive_to_dictionary_dyn::<u16, K>(array),
808 ArrowDataType::UInt32 => primitive_to_dictionary_dyn::<u32, K>(array),
809 ArrowDataType::UInt64 => primitive_to_dictionary_dyn::<u64, K>(array),
810 ArrowDataType::BinaryView => {
811 binview_to_dictionary::<K>(array.as_any().downcast_ref().unwrap())
812 .map(|arr| arr.boxed())
813 },
814 ArrowDataType::Utf8View => {
815 utf8view_to_dictionary::<K>(array.as_any().downcast_ref().unwrap())
816 .map(|arr| arr.boxed())
817 },
818 ArrowDataType::LargeUtf8 => utf8_to_dictionary_dyn::<i64, K>(array),
819 ArrowDataType::LargeBinary => binary_to_dictionary_dyn::<i64, K>(array),
820 ArrowDataType::Time64(_) => primitive_to_dictionary_dyn::<i64, K>(array),
821 ArrowDataType::Timestamp(_, _) => primitive_to_dictionary_dyn::<i64, K>(array),
822 ArrowDataType::Date32 => primitive_to_dictionary_dyn::<i32, K>(array),
823 _ => polars_bail!(ComputeError:
824 "unsupported output type for dictionary packing: {dict_value_type:?}"
825 ),
826 }
827}
828
829fn from_to_binview(
830 array: &dyn Array,
831 from_type: &ArrowDataType,
832 to_type: &ArrowDataType,
833) -> PolarsResult<BinaryViewArray> {
834 use ArrowDataType::*;
835 let binview = match from_type {
836 UInt8 => primitive_to_binview_dyn::<u8>(array),
837 UInt16 => primitive_to_binview_dyn::<u16>(array),
838 UInt32 => primitive_to_binview_dyn::<u32>(array),
839 UInt64 => primitive_to_binview_dyn::<u64>(array),
840 Int8 => primitive_to_binview_dyn::<i8>(array),
841 Int16 => primitive_to_binview_dyn::<i16>(array),
842 Int32 => primitive_to_binview_dyn::<i32>(array),
843 Int64 => primitive_to_binview_dyn::<i64>(array),
844 Float32 => primitive_to_binview_dyn::<f32>(array),
845 Float64 => primitive_to_binview_dyn::<f64>(array),
846 Binary => binary_to_binview::<i32>(array.as_any().downcast_ref().unwrap()),
847 FixedSizeBinary(_) => fixed_size_binary_to_binview(array.as_any().downcast_ref().unwrap()),
848 LargeBinary => binary_to_binview::<i64>(array.as_any().downcast_ref().unwrap()),
849 _ => polars_bail!(InvalidOperation:
850 "casting from {from_type:?} to {to_type:?} not supported",
851 ),
852 };
853 Ok(binview)
854}