Path: blob/main/crates/polars-compute/src/cast/dictionary_to.rs
6939 views
use arrow::array::{Array, DictionaryArray, DictionaryKey};1use arrow::datatypes::ArrowDataType;2use arrow::match_integer_type;3use polars_error::{PolarsResult, polars_bail};45use super::{CastOptionsImpl, cast, primitive_to_primitive};67macro_rules! key_cast {8($keys:expr, $values:expr, $array:expr, $to_keys_type:expr, $to_type:ty, $to_datatype:expr) => {{9let cast_keys = primitive_to_primitive::<_, $to_type>($keys, $to_keys_type);1011// Failure to cast keys (because they don't fit in the12// target type) results in NULL values;13if cast_keys.null_count() > $keys.null_count() {14polars_bail!(ComputeError: "overflow")15}16// SAFETY: this is safe because given a type `T` that fits in a `usize`, casting it to type `P` either overflows or also fits in a `usize`17unsafe {18DictionaryArray::try_new_unchecked($to_datatype, cast_keys, $values.clone())19}20.map(|x| x.boxed())21}};22}2324pub(super) fn dictionary_cast_dyn<K: DictionaryKey + num_traits::NumCast>(25array: &dyn Array,26to_type: &ArrowDataType,27options: CastOptionsImpl,28) -> PolarsResult<Box<dyn Array>> {29let array = array.as_any().downcast_ref::<DictionaryArray<K>>().unwrap();30let keys = array.keys();31let values = array.values();3233match to_type {34ArrowDataType::Dictionary(to_keys_type, to_values_type, _) => {35let values = cast(values.as_ref(), to_values_type, options)?;3637// create the appropriate array type38let to_key_type = (*to_keys_type).into();3940// SAFETY:41// we return an error on overflow so the integers remain within bounds42match_integer_type!(to_keys_type, |$T| {43key_cast!(keys, values, array, &to_key_type, $T, to_type.clone())44})45},46_ => unimplemented!(),47}48}495051