Repository: pola-rs/polars
File: crates/polars-core/src/series/into.rs (Rust)

Code before:
use polars_compute::cast::cast_unchecked;

use crate::prelude::*;

impl Series {
    /// Returns a reference to the Arrow ArrayRef
    #[inline]
    pub fn array_ref(&self, chunk_idx: usize) -> &ArrayRef {
        &self.chunks()[chunk_idx] as &ArrayRef
    }

    /// Convert a chunk in the Series to the correct Arrow type.
    /// This conversion is needed because polars doesn't use a
    /// 1 on 1 mapping for logical/categoricals, etc.
    pub fn to_arrow(&self, chunk_idx: usize, compat_level: CompatLevel) -> ArrayRef {
        match self.dtype() {
            // make sure that we recursively apply all logical types.
            #[cfg(feature = "dtype-struct")]
            dt @ DataType::Struct(fields) => {
                let ca = self.struct_().unwrap();
                let arr = ca.downcast_chunks().get(chunk_idx).unwrap();
                let values = arr
                    .values()
                    .iter()
                    .zip(fields.iter())
                    .map(|(values, field)| {
                        let dtype = &field.dtype;
                        let s = unsafe {
                            Series::from_chunks_and_dtype_unchecked(
                                PlSmallStr::EMPTY,
                                vec![values.clone()],
                                &dtype.to_physical(),
                            )
                            .from_physical_unchecked(dtype)
                            .unwrap()
                        };
                        s.to_arrow(0, compat_level)
                    })
                    .collect::<Vec<_>>();
                StructArray::new(
                    dt.to_arrow(compat_level),
                    arr.len(),
                    values,
                    arr.validity().cloned(),
                )
                .boxed()
            },
            // special list branch to
            // make sure that we recursively apply all logical types.
            DataType::List(inner) => {
                let ca = self.list().unwrap();

Review comment (refactor):
drive-by, recurse on the `&dyn Array` of the chunk, removes duplicated `downcast_chunks().get()` in the function


Code after:
use polars_compute::cast::cast_unchecked;

use crate::prelude::*;

impl Series {
    /// Returns a reference to the Arrow ArrayRef
    #[inline]
    pub fn array_ref(&self, chunk_idx: usize) -> &ArrayRef {
        &self.chunks()[chunk_idx] as &ArrayRef
    }

    /// Convert a chunk in the Series to the correct Arrow type.
    /// This conversion is needed because polars doesn't use a
    /// 1 on 1 mapping for logical/categoricals, etc.
    pub fn to_arrow(&self, chunk_idx: usize, compat_level: CompatLevel) -> ArrayRef {
        ToArrowConverter { compat_level }
            .array_to_arrow(self.chunks().get(chunk_idx).unwrap().as_ref(), self.dtype())
    }
}

pub struct ToArrowConverter {
    pub compat_level: CompatLevel,
}

impl ToArrowConverter {
    pub fn array_to_arrow(&mut self, array: &dyn Array, dtype: &DataType) -> Box<dyn Array> {
        match dtype {
            // make sure that we recursively apply all logical types.
            #[cfg(feature = "dtype-struct")]
            DataType::Struct(fields) => {
                use arrow::array::StructArray;

                let arr: &StructArray = array.as_any().downcast_ref().unwrap();
                let values = arr
                    .values()
                    .iter()
                    .zip(fields.iter())
                    .map(|(values, field)| self.array_to_arrow(values.as_ref(), field.dtype()))
                    .collect::<Vec<_>>();

                StructArray::new(
                    ArrowDataType::Struct(
                        fields
                            .iter()
                            .map(|x| x.name())
                            .zip(values.iter().map(|x| x.dtype()))
                            .map(|(name, dtype)| ArrowField::new(name.clone(), dtype.clone(), true))
                            .collect(),
                    ),
                    arr.len(),
                    values,