Repository: pola-rs/polars
File: crates/polars-compute/src/cast/binview_to.rs (Rust)

Code before:
pub(super) fn try_binview_to_fixed_size_list<T, const IS_LITTLE_ENDIAN: bool>(
    from: &BinaryViewArray,
    array_items: usize,
) -> PolarsResult<FixedSizeListArray>
where
    T: FromBytes + NativeType,
    for<'a> &'a <T as FromBytes>::Bytes: TryFrom<&'a [u8]>,
{
    let element_size = std::mem::size_of::<T>();
    let from_bytes = if IS_LITTLE_ENDIAN {
        <T as FromBytes>::from_le_bytes
    } else {
        <T as FromBytes>::from_be_bytes
    };

    // It would be nice to have a fast path that just use a memory copy.
    // However, that is only possible if all the binaryviews are the correct
    // length, and checking that requires iterating over all of them, so it's
    // not obvious that would actually be much of a speed up.
    let primitive_length = from.len() * array_items;
    let mut out: Vec<T> = Vec::with_capacity(primitive_length);
    let mut validity = MutableBitmap::from_len_set(from.len());

    // Values for primitive array when values are NULL, so we don't leave
    // uninitialized memory.
    let empty = vec![T::default(); array_items];

    for (index, value) in from.iter().enumerate() {
        if let Some(value) = value
            && value.len() == element_size * array_items
        {
            for j in 0..array_items {
                let jth_bytes = &value[(j * element_size)..((j + 1) * element_size)];
                // # Safety
                // We just made sure that the slice has length `element_size`
                let byte_array = unsafe { jth_bytes.try_into().unwrap_unchecked() };
                let jth_value = from_bytes(byte_array);

                let write_index = array_items * index + j;
                debug_assert!(write_index < primitive_length);
                // # Safety
                // - The target index is smaller than the vector's pre-allocated capacity.
                unsafe {
                    std::ptr::write(out.as_mut_ptr().add(write_index), jth_value);
                }
            }
        } else {
            validity.set(index, false);
            let write_index = array_items * index;
            debug_assert!(write_index < primitive_length);
            debug_assert!((write_index + (array_items - 1)) < primitive_length);

Review comment (refactor):
Remove this - it's fine to use uninitialized memory for primitive types. They are considered POD, and don't have any `Drop` destructors.


Code after:
    array_width: usize,
) -> PolarsResult<FixedSizeListArray>
where
    T: FromBytes + NativeType,
    for<'a> &'a <T as FromBytes>::Bytes: TryFrom<&'a [u8]>,
{
    let element_size = std::mem::size_of::<T>();
    // The maximum number of primitives in the result:
    let primitive_length = from.len().checked_mul(array_width).ok_or_else(|| {
        polars_err!(
            InvalidOperation:
            "array chunk length * number of items ({} * {}) is too large",
            from.len(),
            array_width
        )
    })?;
    // The size of each array, in bytes:
    let row_size_bytes = element_size.checked_mul(array_width).ok_or_else(|| {
        polars_err!(
            InvalidOperation:
            "array size in bytes ({} * {}) is too large",
            element_size,
            array_width
        )
    })?;

    let mut out: Vec<T> = vec![T::zeroed(); primitive_length];
    let (out_u8_ptr, out_len_bytes) = {
        let out_u8_slice = cast_slice_mut::<_, u8>(out.as_mut());
        (out_u8_slice.as_mut_ptr(), out_u8_slice.len())
    };
    assert_eq!(out_len_bytes, row_size_bytes * from.len());
    let mut validity = MutableBitmap::from_len_set(from.len());

    for (index, value) in from.iter().enumerate() {
        if let Some(value) = value
            && value.len() == row_size_bytes
        {
            if cfg!(target_endian = "little") && IS_LITTLE_ENDIAN {
                // Fast path, we can just copy the data with no need to
                // reinterpret.
                let write_index = index * row_size_bytes;
                debug_assert!(value.is_empty() || write_index < out_len_bytes);
                debug_assert!(value.is_empty() || (write_index + value.len() - 1 < out_len_bytes));
                // # Safety
                // - The start index is smaller than `out`'s capacity.
                // - The end index is smaller than `out`'s capacity.
                unsafe {
                    copy_nonoverlapping(value.as_ptr(), out_u8_ptr.add(write_index), value.len());
                }
            } else {