This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 99c537441d Enhance list casting, adding more cases for list views 
(#9274)
99c537441d is described below

commit 99c537441da3f4c16863a3e3c7512899db1a9ca0
Author: Jeffrey Vo <[email protected]>
AuthorDate: Tue Feb 3 00:34:50 2026 +0900

    Enhance list casting, adding more cases for list views (#9274)
    
    # Which issue does this PR close?
    
    <!--
    We generally require a GitHub issue to be filed for all bug fixes and
    enhancements and this helps us generate change logs for our releases.
    You can link an issue to this PR using the GitHub syntax.
    -->
    
    - Closes #9264
    
    # Rationale for this change
    
    <!--
    Why are you proposing this change? If this is already explained clearly
    in the issue then this section is not needed.
    Explaining clearly why changes are proposed helps reviewers understand
    your changes and offer better suggestions for fixes.
    -->
    
    While we do have support for casting list views, some cases are missing.
    This PR goes through the list casting logic for all list types and tries
    to ensure we have comprehensive & consistent coverage for casting cases,
    also refactoring to try make this coverage more obvious at a glance.
    
    # What changes are included in this PR?
    
    <!--
    There is no need to duplicate the description in the issue here but it
    is sometimes worth providing a summary of the individual changes in this
    PR.
    -->
    
    This PR has a mix of new features (new casts supported) and refactoring.
    
    New features:
    
    - Cast from `List`/`LargeList` to `Utf8View`
      - We supported casting to `Utf8`/`LargeUtf8`, but view was missing
    - Cast from `ListView`/`LargeListView` to string types
    - Cast between list view types when inner types differ
    - Previously we could cast `ListView` to `LargeListView`, but casting
    `ListView<Int32>` to `ListView<Float32>` was not supported; this adds
    that ability, which regular `List` arrays supported
    - Cast non-list types to `ListView`/`LargeListView`
    - Cast `FixedSizeList` to `ListView`/`LargeListView`
    - Cast `List`/`LargeList` to `ListView`/`LargeListView` when inner types
    differ
    - This again was something we supported, except we never accounted for
    the inner types differing; so fix to ensure we cast inner types
    - Cast `List` to `LargeListView`, `LargeList` to `ListView`, `ListView`
    to `LargeList`, `LargeListView` to `List`
      - These cross-offset casts were missing
    - Cast `ListView`/`LargeListView` to `FixedSizeList`
    
    Refactors:
    
    - Consolidate arms in `cast_with_options` to organize the list casts
    together so it's easier to see we have coverage for casting between all
    list types
    - Condense testing code, trying to use existing downcast methods and
    array builders to reduce verbosity
    - Consolidate list view cast helper functions into the list cast helper
    functions file (`arrow-cast/src/cast/list_view.rs` merged into
    `arrow-cast/src/cast/list.rs`) since it's easier to track them together,
    especially with the cross list <-> listview cast functions
    
    # Are these changes tested?
    
    <!--
    We typically require tests for all PRs in order to:
    1. Prevent the code from being accidentally broken by subsequent changes
    2. Serve as another way to document the expected behavior of the code
    
    If tests are not included in your PR, please explain why (for example,
    are they covered by existing tests)?
    -->
    
    Yes, added new tests.
    
    # Are there any user-facing changes?
    
    <!--
    If there are user-facing changes then we may require documentation to be
    updated before approving the PR.
    
    If there are any breaking changes to public APIs, please call them out.
    -->
    
    No.
---
 arrow-buffer/src/builder/null.rs |   7 +
 arrow-cast/src/cast/list.rs      | 354 ++++++++++++++--
 arrow-cast/src/cast/list_view.rs |  91 -----
 arrow-cast/src/cast/mod.rs       | 848 ++++++++++++++++++++++++++++-----------
 4 files changed, 940 insertions(+), 360 deletions(-)

diff --git a/arrow-buffer/src/builder/null.rs b/arrow-buffer/src/builder/null.rs
index 2ffd4dcd4c..e98f25817a 100644
--- a/arrow-buffer/src/builder/null.rs
+++ b/arrow-buffer/src/builder/null.rs
@@ -147,6 +147,13 @@ impl NullBufferBuilder {
         }
     }
 
+    /// Sets a bit in the builder at `index`
+    #[inline]
+    pub fn set_bit(&mut self, index: usize, v: bool) {
+        self.materialize_if_needed();
+        self.bitmap_builder.as_mut().unwrap().set_bit(index, v);
+    }
+
     /// Gets a bit in the buffer at `index`
     #[inline]
     pub fn is_valid(&self, index: usize) -> bool {
diff --git a/arrow-cast/src/cast/list.rs b/arrow-cast/src/cast/list.rs
index f6c8d2465c..5d7209ee11 100644
--- a/arrow-cast/src/cast/list.rs
+++ b/arrow-cast/src/cast/list.rs
@@ -17,19 +17,58 @@
 
 use crate::cast::*;
 
-/// Helper function that takes a primitive array and casts to a (generic) list 
array.
+/// Converts a non-list array to a list array where every element is a single 
element
+/// list. `NULL`s in the original array become `[NULL]` (i.e. output list array
+/// contains no nulls since it wraps all input nulls in a single element list).
+///
+/// For example: `Int32([1, NULL, 2]) -> List<Int32>([[1], [NULL], [2]])`
 pub(crate) fn cast_values_to_list<O: OffsetSizeTrait>(
     array: &dyn Array,
     to: &FieldRef,
     cast_options: &CastOptions,
 ) -> Result<ArrayRef, ArrowError> {
+    if array.len() > O::MAX_OFFSET {
+        return Err(ArrowError::ComputeError(format!(
+            "Offset overflow when casting from {} to {}",
+            array.data_type(),
+            to.data_type()
+        )));
+    }
     let values = cast_with_options(array, to.data_type(), cast_options)?;
     let offsets = OffsetBuffer::from_repeated_length(1, values.len());
     let list = GenericListArray::<O>::try_new(to.clone(), offsets, values, 
None)?;
     Ok(Arc::new(list))
 }
 
-/// Helper function that takes a primitive array and casts to a fixed size 
list array.
+/// Same as [`cast_values_to_list`] but output list view array.
+pub(crate) fn cast_values_to_list_view<O: OffsetSizeTrait>(
+    array: &dyn Array,
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    if array.len() > O::MAX_OFFSET {
+        return Err(ArrowError::ComputeError(format!(
+            "Offset overflow when casting from {} to {}",
+            array.data_type(),
+            to.data_type()
+        )));
+    }
+    let values = cast_with_options(array, to.data_type(), cast_options)?;
+    let offsets = (0..values.len())
+        .map(|index| O::usize_as(index))
+        .collect::<Vec<O>>();
+    let list = GenericListViewArray::<O>::try_new(
+        to.clone(),
+        offsets.into(),
+        vec![O::one(); values.len()].into(),
+        values,
+        None,
+    )?;
+    Ok(Arc::new(list))
+}
+
+/// Same as [`cast_values_to_list`] but output fixed size list array with 
element
+/// size 1.
 pub(crate) fn cast_values_to_fixed_size_list(
     array: &dyn Array,
     to: &FieldRef,
@@ -41,6 +80,10 @@ pub(crate) fn cast_values_to_fixed_size_list(
     Ok(Arc::new(list))
 }
 
+/// Cast fixed size list array to inner values type, essentially flattening the
+/// lists.
+///
+/// For example: `FixedSizeList<Int32, 2>([[1, 2], [3, 4]]) -> Int32([1, 2, 3, 
4])`
 pub(crate) fn cast_single_element_fixed_size_list_to_values(
     array: &dyn Array,
     to: &DataType,
@@ -50,19 +93,58 @@ pub(crate) fn cast_single_element_fixed_size_list_to_values(
     cast_with_options(values, to, cast_options)
 }
 
-pub(crate) fn cast_fixed_size_list_to_list<OffsetSize>(
+fn cast_fixed_size_list_to_list_inner<OffsetSize: OffsetSizeTrait, const 
IS_LIST_VIEW: bool>(
     array: &dyn Array,
-) -> Result<ArrayRef, ArrowError>
-where
-    OffsetSize: OffsetSizeTrait,
-{
-    let fixed_size_list: &FixedSizeListArray = array.as_fixed_size_list();
-    let list: GenericListArray<OffsetSize> = fixed_size_list.clone().into();
-    Ok(Arc::new(list))
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    let array = array.as_fixed_size_list();
+    let DataType::FixedSizeList(inner_field, size) = array.data_type() else {
+        unreachable!()
+    };
+    let array = if to.data_type() != inner_field.data_type() {
+        // To transform inner type, can first cast to FSL with new inner type.
+        let fsl_to = DataType::FixedSizeList(to.clone(), *size);
+        let array = cast_with_options(array, &fsl_to, cast_options)?;
+        array.as_fixed_size_list().clone()
+    } else {
+        array.clone()
+    };
+    if IS_LIST_VIEW {
+        let list: GenericListViewArray<OffsetSize> = array.into();
+        Ok(Arc::new(list))
+    } else {
+        let list: GenericListArray<OffsetSize> = array.into();
+        Ok(Arc::new(list))
+    }
 }
 
+/// Cast fixed size list arrays to list arrays, maintaining the lengths of the 
inner
+/// lists.
+///
+/// For example: `FixedSizeList<Int32, 2>([[1, 2], [3, 4]]) -> 
List<Int32>([[1, 2], [3, 4]])`
+pub(crate) fn cast_fixed_size_list_to_list<OffsetSize: OffsetSizeTrait>(
+    array: &dyn Array,
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    cast_fixed_size_list_to_list_inner::<OffsetSize, false>(array, to, 
cast_options)
+}
+
+/// Same as [`cast_fixed_size_list_to_list`] but output list view array.
+pub(crate) fn cast_fixed_size_list_to_list_view<OffsetSize: OffsetSizeTrait>(
+    array: &dyn Array,
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    cast_fixed_size_list_to_list_inner::<OffsetSize, true>(array, to, 
cast_options)
+}
+
+/// Cast list to fixed size list array. If any inner list size does not match 
the
+/// size of the output fixed size list array, depending on `cast_options` we 
either
+/// output `NULL` for that element (safe) or raise an error.
 pub(crate) fn cast_list_to_fixed_size_list<OffsetSize>(
-    array: &GenericListArray<OffsetSize>,
+    array: &dyn Array,
     field: &FieldRef,
     size: i32,
     cast_options: &CastOptions,
@@ -70,19 +152,19 @@ pub(crate) fn cast_list_to_fixed_size_list<OffsetSize>(
 where
     OffsetSize: OffsetSizeTrait,
 {
+    let array = array.as_list::<OffsetSize>();
+
     let cap = array.len() * size as usize;
 
+    let mut null_builder = NullBufferBuilder::new(array.len());
+    if let Some(nulls) = array.nulls().filter(|b| b.null_count() > 0) {
+        null_builder.append_buffer(nulls);
+    } else {
+        null_builder.append_n_non_nulls(array.len());
+    }
+
     // Whether the resulting array may contain null lists
     let nullable = cast_options.safe || array.null_count() != 0;
-    let mut nulls = nullable.then(|| {
-        let mut buffer = BooleanBufferBuilder::new(array.len());
-        match array.nulls() {
-            Some(n) => buffer.append_buffer(n.inner()),
-            None => buffer.append_n(array.len(), true),
-        }
-        buffer
-    });
-
     // Nulls in FixedSizeListArray take up space and so we must pad the values
     let values = array.values().to_data();
     let mut mutable = MutableArrayData::new(vec![&values], nullable, cap);
@@ -112,7 +194,7 @@ where
                 }
                 // Pad this slice with nulls
                 mutable.extend_nulls(size as _);
-                nulls.as_mut().unwrap().set_bit(idx, false);
+                null_builder.set_bit(idx, false);
                 // Set last_pos to the end of this slice's values
                 last_pos = end_pos
             } else {
@@ -138,13 +220,58 @@ where
     // Cast the inner values if necessary
     let values = cast_with_options(values.as_ref(), field.data_type(), 
cast_options)?;
 
-    // Construct the FixedSizeListArray
-    let nulls = nulls.map(|mut x| x.finish().into());
-    let array = FixedSizeListArray::try_new(field.clone(), size, values, 
nulls)?;
+    let array = FixedSizeListArray::try_new(field.clone(), size, values, 
null_builder.build())?;
     Ok(Arc::new(array))
 }
 
-/// Helper function that takes an Generic list container and casts the inner 
datatype.
+/// Same as [`cast_list_to_fixed_size_list`] but for list view arrays.
+pub(crate) fn cast_list_view_to_fixed_size_list<O: OffsetSizeTrait>(
+    array: &dyn Array,
+    field: &FieldRef,
+    size: i32,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    let array = array.as_list_view::<O>();
+
+    let mut null_builder = NullBufferBuilder::new(array.len());
+    if let Some(nulls) = array.nulls().filter(|b| b.null_count() > 0) {
+        null_builder.append_buffer(nulls);
+    } else {
+        null_builder.append_n_non_nulls(array.len());
+    }
+
+    let nullable = cast_options.safe || array.null_count() != 0;
+    let values = array.values().to_data();
+    let cap = array.len() * size as usize;
+    let mut mutable = MutableArrayData::new(vec![&values], nullable, cap);
+
+    for idx in 0..array.len() {
+        let offset = array.value_offset(idx).as_usize();
+        let len = array.value_size(idx).as_usize();
+
+        if len != size as usize {
+            // Nulls in FixedSizeListArray take up space and so we must pad 
the values
+            if cast_options.safe || array.is_null(idx) {
+                mutable.extend_nulls(size as _);
+                null_builder.set_bit(idx, false);
+            } else {
+                return Err(ArrowError::CastError(format!(
+                    "Cannot cast to FixedSizeList({size}): value at index 
{idx} has length {len}",
+                )));
+            }
+        } else {
+            mutable.extend(0, offset, offset + len);
+        }
+    }
+
+    let values = make_array(mutable.freeze());
+    let values = cast_with_options(values.as_ref(), field.data_type(), 
cast_options)?;
+
+    let array = FixedSizeListArray::try_new(field.clone(), size, values, 
null_builder.build())?;
+    Ok(Arc::new(array))
+}
+
+/// Casting between list arrays of same offset size; we cast only the inner 
type.
 pub(crate) fn cast_list_values<O: OffsetSizeTrait>(
     array: &dyn Array,
     to: &FieldRef,
@@ -160,7 +287,24 @@ pub(crate) fn cast_list_values<O: OffsetSizeTrait>(
     )?))
 }
 
-/// Cast the container type of List/Largelist array along with the inner 
datatype
+/// Casting between list view arrays of same offset size; we cast only the 
inner type.
+pub(crate) fn cast_list_view_values<O: OffsetSizeTrait>(
+    array: &dyn Array,
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    let list = array.as_list_view::<O>();
+    let values = cast_with_options(list.values(), to.data_type(), 
cast_options)?;
+    Ok(Arc::new(GenericListViewArray::<O>::try_new(
+        to.clone(),
+        list.offsets().clone(),
+        list.sizes().clone(),
+        values,
+        list.nulls().cloned(),
+    )?))
+}
+
+/// Casting between list arrays of different offset size (e.g. List -> 
LargeList)
 pub(crate) fn cast_list<I: OffsetSizeTrait, O: OffsetSizeTrait>(
     array: &dyn Array,
     field: &FieldRef,
@@ -171,10 +315,12 @@ pub(crate) fn cast_list<I: OffsetSizeTrait, O: 
OffsetSizeTrait>(
     let offsets = list.offsets();
     let nulls = list.nulls().cloned();
 
-    if !O::IS_LARGE && values.len() > i32::MAX as usize {
-        return Err(ArrowError::ComputeError(
-            "LargeList too large to cast to List".into(),
-        ));
+    if offsets.last().unwrap().as_usize() > O::MAX_OFFSET {
+        return Err(ArrowError::ComputeError(format!(
+            "Offset overflow when casting from {} to {}",
+            array.data_type(),
+            field.data_type()
+        )));
     }
 
     // Recursively cast values
@@ -191,3 +337,151 @@ pub(crate) fn cast_list<I: OffsetSizeTrait, O: 
OffsetSizeTrait>(
         nulls,
     )?))
 }
+
+/// Casting list view arrays to list.
+pub(crate) fn cast_list_view_to_list<I, O>(
+    array: &dyn Array,
+    to: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError>
+where
+    I: OffsetSizeTrait,
+    // We need ArrowPrimitiveType here to be able to create indices array for 
the
+    // take kernel.
+    O: ArrowPrimitiveType,
+    O::Native: OffsetSizeTrait,
+{
+    let list_view = array.as_list_view::<I>();
+    let list_view_offsets = list_view.offsets();
+    let sizes = list_view.sizes();
+
+    let mut take_indices: Vec<O::Native> = 
Vec::with_capacity(list_view.values().len());
+    let mut offsets: Vec<O::Native> = Vec::with_capacity(list_view.len() + 1);
+    use num_traits::Zero;
+    offsets.push(O::Native::zero());
+
+    for i in 0..list_view.len() {
+        if list_view.is_null(i) {
+            offsets.push(O::Native::usize_as(take_indices.len()));
+            continue;
+        }
+
+        let offset = list_view_offsets[i].as_usize();
+        let size = sizes[i].as_usize();
+
+        for value_index in offset..offset + size {
+            take_indices.push(O::Native::usize_as(value_index));
+        }
+
+        // Must guard all cases since ListView<i32> can overflow List<i32>
+        // e.g. if offsets of [0, 0, 0] and sizes [i32::MAX, i32::MAX, 
i32::MAX]
+        if take_indices.len() > O::Native::MAX_OFFSET {
+            return Err(ArrowError::ComputeError(format!(
+                "Offset overflow when casting from {} to {}",
+                array.data_type(),
+                to.data_type()
+            )));
+        }
+        offsets.push(O::Native::usize_as(take_indices.len()));
+    }
+
+    // Form a contiguous values array
+    let take_indices = PrimitiveArray::<O>::from_iter_values(take_indices);
+    let values = arrow_select::take::take(list_view.values(), &take_indices, 
None)?;
+    let values = cast_with_options(&values, to.data_type(), cast_options)?;
+
+    Ok(Arc::new(GenericListArray::<O::Native>::try_new(
+        to.clone(),
+        OffsetBuffer::new(offsets.into()),
+        values,
+        list_view.nulls().cloned(),
+    )?))
+}
+
+/// Casting between list view arrays of different offset size (e.g. ListView 
-> LargeListView)
+pub(crate) fn cast_list_view<I: OffsetSizeTrait, O: OffsetSizeTrait>(
+    array: &dyn Array,
+    to_field: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    let list_view = array.as_list_view::<I>();
+
+    // Recursively cast values
+    let values = cast_with_options(list_view.values(), to_field.data_type(), 
cast_options)?;
+
+    let offsets = list_view
+        .offsets()
+        .iter()
+        .map(|offset| {
+            let offset = offset.as_usize();
+            if offset > O::MAX_OFFSET {
+                return Err(ArrowError::ComputeError(format!(
+                    "Offset overflow when casting from {} to {}",
+                    array.data_type(),
+                    to_field.data_type()
+                )));
+            }
+            Ok(O::usize_as(offset))
+        })
+        .collect::<Result<Vec<O>, _>>()?;
+    let sizes = list_view
+        .sizes()
+        .iter()
+        .map(|size| {
+            let size = size.as_usize();
+            if size > O::MAX_OFFSET {
+                return Err(ArrowError::ComputeError(format!(
+                    "Offset overflow when casting from {} to {}",
+                    array.data_type(),
+                    to_field.data_type()
+                )));
+            }
+            Ok(O::usize_as(size))
+        })
+        .collect::<Result<Vec<O>, _>>()?;
+    Ok(Arc::new(GenericListViewArray::<O>::try_new(
+        to_field.clone(),
+        offsets.into(),
+        sizes.into(),
+        values,
+        list_view.nulls().cloned(),
+    )?))
+}
+
+/// Casting list arrays to list view.
+pub(crate) fn cast_list_to_list_view<I: OffsetSizeTrait, O: OffsetSizeTrait>(
+    array: &dyn Array,
+    to_field: &FieldRef,
+    cast_options: &CastOptions,
+) -> Result<ArrayRef, ArrowError> {
+    let list = array.as_list::<I>();
+    let (_field, offsets, values, nulls) = list.clone().into_parts();
+
+    let len = offsets.len() - 1;
+    let mut sizes = Vec::with_capacity(len);
+    let mut view_offsets = Vec::with_capacity(len);
+    for (i, offset) in offsets.iter().enumerate().take(len) {
+        let offset = offset.as_usize();
+        let size = offsets[i + 1].as_usize() - offset;
+
+        if offset > O::MAX_OFFSET || size > O::MAX_OFFSET {
+            return Err(ArrowError::ComputeError(format!(
+                "Offset overflow when casting from {} to {}",
+                array.data_type(),
+                to_field.data_type()
+            )));
+        }
+
+        view_offsets.push(O::usize_as(offset));
+        sizes.push(O::usize_as(size));
+    }
+    let values = cast_with_options(&values, to_field.data_type(), 
cast_options)?;
+    let array = GenericListViewArray::<O>::new(
+        to_field.clone(),
+        view_offsets.into(),
+        sizes.into(),
+        values,
+        nulls,
+    );
+    Ok(Arc::new(array))
+}
diff --git a/arrow-cast/src/cast/list_view.rs b/arrow-cast/src/cast/list_view.rs
deleted file mode 100644
index 0fdab8c624..0000000000
--- a/arrow-cast/src/cast/list_view.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use crate::cast::*;
-
-/// Helper function to cast a list view to a list
-pub(crate) fn cast_list_view_to_list<O: OffsetSizeTrait>(
-    array: &dyn Array,
-    to: &FieldRef,
-    cast_options: &CastOptions,
-) -> Result<ArrayRef, ArrowError> {
-    let list_view = array.as_list_view::<O>();
-    let list_view_offsets = list_view.offsets();
-    let sizes = list_view.sizes();
-    let source_values = list_view.values();
-
-    // Construct the indices and offsets for the new list array by iterating 
over the list view subarrays
-    let mut indices = Vec::with_capacity(list_view.values().len());
-    let mut offsets = Vec::with_capacity(list_view.len() + 1);
-    // Add the offset for the first subarray
-    offsets.push(O::usize_as(0));
-    for i in 0..list_view.len() {
-        // For each subarray, add the indices of the values to take
-        let offset = list_view_offsets[i].as_usize();
-        let size = sizes[i].as_usize();
-        let end = offset + size;
-        for j in offset..end {
-            indices.push(j as i32);
-        }
-        // Add the offset for the next subarray
-        offsets.push(O::usize_as(indices.len()));
-    }
-
-    // Take the values from the source values using the indices, creating a 
new array
-    let values = arrow_select::take::take(source_values, 
&Int32Array::from(indices), None)?;
-
-    // Cast the values to the target data type
-    let values = cast_with_options(&values, to.data_type(), cast_options)?;
-
-    Ok(Arc::new(GenericListArray::<O>::try_new(
-        to.clone(),
-        OffsetBuffer::new(offsets.into()),
-        values,
-        list_view.nulls().cloned(),
-    )?))
-}
-
-pub(crate) fn cast_list_view<I: OffsetSizeTrait, O: OffsetSizeTrait>(
-    array: &dyn Array,
-    to_field: &FieldRef,
-    cast_options: &CastOptions,
-) -> Result<ArrayRef, ArrowError> {
-    let list_view = array.as_list_view::<I>();
-    let (_field, offsets, sizes, values, nulls) = 
list_view.clone().into_parts();
-
-    // Recursively cast values
-    let values = cast_with_options(&values, to_field.data_type(), 
cast_options)?;
-
-    let new_offsets: Vec<_> = offsets.iter().map(|x| 
O::usize_as(x.as_usize())).collect();
-    let new_sizes: Vec<_> = sizes.iter().map(|x| 
O::usize_as(x.as_usize())).collect();
-    Ok(Arc::new(GenericListViewArray::<O>::try_new(
-        to_field.clone(),
-        new_offsets.into(),
-        new_sizes.into(),
-        values,
-        nulls,
-    )?))
-}
-
-pub(crate) fn cast_list_to_list_view<OffsetSize>(array: &dyn Array) -> 
Result<ArrayRef, ArrowError>
-where
-    OffsetSize: OffsetSizeTrait,
-{
-    let list = array.as_list::<OffsetSize>();
-    let list_view: GenericListViewArray<OffsetSize> = list.clone().into();
-    Ok(Arc::new(list_view))
-}
diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs
index 34416eb91b..ff99e1d6a5 100644
--- a/arrow-cast/src/cast/mod.rs
+++ b/arrow-cast/src/cast/mod.rs
@@ -40,7 +40,6 @@
 mod decimal;
 mod dictionary;
 mod list;
-mod list_view;
 mod map;
 mod run_array;
 mod string;
@@ -71,7 +70,6 @@ use arrow_schema::*;
 use arrow_select::take::take;
 use num_traits::{NumCast, ToPrimitive, cast::AsPrimitive};
 
-use crate::cast::list_view::{cast_list_to_list_view, cast_list_view, 
cast_list_view_to_list};
 pub use decimal::{DecimalCast, rescale_decimal};
 
 /// CastOptions provides a way to override the default cast behaviors
@@ -113,37 +111,28 @@ pub fn can_cast_types(from_type: &DataType, to_type: 
&DataType) -> bool {
         (RunEndEncoded(_, value_type), _) => 
can_cast_types(value_type.data_type(), to_type),
         (_, RunEndEncoded(_, value_type)) => can_cast_types(from_type, 
value_type.data_type()),
         (_, Dictionary(_, value_type)) => can_cast_types(from_type, 
value_type),
-        (List(list_from) | LargeList(list_from), List(list_to) | 
LargeList(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (List(list_from) | LargeList(list_from), Utf8 | LargeUtf8) => {
-            can_cast_types(list_from.data_type(), to_type)
-        }
-        (List(list_from) | LargeList(list_from), FixedSizeList(list_to, _)) => 
{
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (List(list_from) | LargeList(list_from), ListView(list_to) | 
LargeListView(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (List(_), _) => false,
-        (ListView(list_from) | LargeListView(list_from), List(list_to) | 
LargeList(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (ListView(list_from), LargeListView(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (LargeListView(list_from), ListView(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
-        (FixedSizeList(list_from, _), List(list_to))
-        | (FixedSizeList(list_from, _), LargeList(list_to)) => {
-            can_cast_types(list_from.data_type(), list_to.data_type())
-        }
+        (
+            List(list_from) | LargeList(list_from) | ListView(list_from) | 
LargeListView(list_from),
+            List(list_to) | LargeList(list_to) | ListView(list_to) | 
LargeListView(list_to),
+        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
+        (
+            List(list_from) | LargeList(list_from) | ListView(list_from) | 
LargeListView(list_from),
+            Utf8 | LargeUtf8 | Utf8View,
+        ) => can_cast_types(list_from.data_type(), to_type),
+        (
+            FixedSizeList(list_from, _),
+            List(list_to) | LargeList(list_to) | ListView(list_to) | 
LargeListView(list_to),
+        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
+        (
+            List(list_from) | LargeList(list_from) | ListView(list_from) | 
LargeListView(list_from),
+            FixedSizeList(list_to, _),
+        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
         (FixedSizeList(inner, size), FixedSizeList(inner_to, size_to)) if size 
== size_to => {
             can_cast_types(inner.data_type(), inner_to.data_type())
         }
-        (_, List(list_to)) => can_cast_types(from_type, list_to.data_type()),
-        (_, LargeList(list_to)) => can_cast_types(from_type, 
list_to.data_type()),
+        (_, List(list_to) | LargeList(list_to) | ListView(list_to) | 
LargeListView(list_to)) => {
+            can_cast_types(from_type, list_to.data_type())
+        }
         (_, FixedSizeList(list_to, size)) if *size == 1 => {
             can_cast_types(from_type, list_to.data_type())
         }
@@ -818,80 +807,112 @@ pub fn cast_with_options(
                 "Casting from type {from_type} to dictionary type {to_type} 
not supported",
             ))),
         },
+        // Casting between lists of same types (cast inner values)
         (List(_), List(to)) => cast_list_values::<i32>(array, to, 
cast_options),
         (LargeList(_), LargeList(to)) => cast_list_values::<i64>(array, to, 
cast_options),
+        (FixedSizeList(_, size_from), FixedSizeList(list_to, size_to)) => {
+            if size_from != size_to {
+                return Err(ArrowError::CastError(
+                    "cannot cast fixed-size-list to fixed-size-list with 
different size".into(),
+                ));
+            }
+            let array = array.as_fixed_size_list();
+            let values = cast_with_options(array.values(), 
list_to.data_type(), cast_options)?;
+            Ok(Arc::new(FixedSizeListArray::try_new(
+                list_to.clone(),
+                *size_from,
+                values,
+                array.nulls().cloned(),
+            )?))
+        }
+        (ListView(_), ListView(to)) => cast_list_view_values::<i32>(array, to, 
cast_options),
+        (LargeListView(_), LargeListView(to)) => {
+            cast_list_view_values::<i64>(array, to, cast_options)
+        }
+        // Casting between different types of lists
+        // List
         (List(_), LargeList(list_to)) => cast_list::<i32, i64>(array, list_to, 
cast_options),
-        (LargeList(_), List(list_to)) => cast_list::<i64, i32>(array, list_to, 
cast_options),
         (List(_), FixedSizeList(field, size)) => {
-            let array = array.as_list::<i32>();
             cast_list_to_fixed_size_list::<i32>(array, field, *size, 
cast_options)
         }
+        (List(_), ListView(list_to)) => {
+            cast_list_to_list_view::<i32, i32>(array, list_to, cast_options)
+        }
+        (List(_), LargeListView(list_to)) => {
+            cast_list_to_list_view::<i32, i64>(array, list_to, cast_options)
+        }
+        // LargeList
+        (LargeList(_), List(list_to)) => cast_list::<i64, i32>(array, list_to, 
cast_options),
         (LargeList(_), FixedSizeList(field, size)) => {
-            let array = array.as_list::<i64>();
             cast_list_to_fixed_size_list::<i64>(array, field, *size, 
cast_options)
         }
-        (ListView(_), List(list_to)) => cast_list_view_to_list::<i32>(array, 
list_to, cast_options),
-        (LargeListView(_), LargeList(list_to)) => {
-            cast_list_view_to_list::<i64>(array, list_to, cast_options)
+        (LargeList(_), ListView(list_to)) => {
+            cast_list_to_list_view::<i64, i32>(array, list_to, cast_options)
+        }
+        (LargeList(_), LargeListView(list_to)) => {
+            cast_list_to_list_view::<i64, i64>(array, list_to, cast_options)
+        }
+        // ListView
+        (ListView(_), List(list_to)) => {
+            cast_list_view_to_list::<i32, Int32Type>(array, list_to, 
cast_options)
+        }
+        (ListView(_), LargeList(list_to)) => {
+            cast_list_view_to_list::<i32, Int64Type>(array, list_to, 
cast_options)
         }
         (ListView(_), LargeListView(list_to)) => {
             cast_list_view::<i32, i64>(array, list_to, cast_options)
         }
+        (ListView(_), FixedSizeList(field, size)) => {
+            cast_list_view_to_fixed_size_list::<i32>(array, field, *size, 
cast_options)
+        }
+        // LargeListView
+        (LargeListView(_), LargeList(list_to)) => {
+            cast_list_view_to_list::<i64, Int64Type>(array, list_to, 
cast_options)
+        }
+        (LargeListView(_), List(list_to)) => {
+            cast_list_view_to_list::<i64, Int32Type>(array, list_to, 
cast_options)
+        }
         (LargeListView(_), ListView(list_to)) => {
             cast_list_view::<i64, i32>(array, list_to, cast_options)
         }
-        (List(_), ListView(_)) => cast_list_to_list_view::<i32>(array),
-        (LargeList(_), LargeListView(_)) => 
cast_list_to_list_view::<i64>(array),
-        (List(_) | LargeList(_), _) => match to_type {
+        (LargeListView(_), FixedSizeList(field, size)) => {
+            cast_list_view_to_fixed_size_list::<i64>(array, field, *size, 
cast_options)
+        }
+        // FixedSizeList
+        (FixedSizeList(_, _), List(list_to)) => {
+            cast_fixed_size_list_to_list::<i32>(array, list_to, cast_options)
+        }
+        (FixedSizeList(_, _), LargeList(list_to)) => {
+            cast_fixed_size_list_to_list::<i64>(array, list_to, cast_options)
+        }
+        (FixedSizeList(_, _), ListView(list_to)) => {
+            cast_fixed_size_list_to_list_view::<i32>(array, list_to, 
cast_options)
+        }
+        (FixedSizeList(_, _), LargeListView(list_to)) => {
+            cast_fixed_size_list_to_list_view::<i64>(array, list_to, 
cast_options)
+        }
+        // List to/from other types
+        (FixedSizeList(_, size), _) if *size == 1 => {
+            cast_single_element_fixed_size_list_to_values(array, to_type, 
cast_options)
+        }
+        // NOTE: we could support FSL to string here too but might be confusing
+        //       since behaviour for size 1 would be different (see arm above)
+        (List(_) | LargeList(_) | ListView(_) | LargeListView(_), _) => match 
to_type {
             Utf8 => value_to_string::<i32>(array, cast_options),
             LargeUtf8 => value_to_string::<i64>(array, cast_options),
+            Utf8View => value_to_string_view(array, cast_options),
             _ => Err(ArrowError::CastError(
                 "Cannot cast list to non-list data types".to_string(),
             )),
         },
-        (FixedSizeList(list_from, size), List(list_to)) => {
-            if list_to.data_type() != list_from.data_type() {
-                // To transform inner type, can first cast to FSL with new 
inner type.
-                let fsl_to = DataType::FixedSizeList(list_to.clone(), *size);
-                let array = cast_with_options(array, &fsl_to, cast_options)?;
-                cast_fixed_size_list_to_list::<i32>(array.as_ref())
-            } else {
-                cast_fixed_size_list_to_list::<i32>(array)
-            }
-        }
-        (FixedSizeList(list_from, size), LargeList(list_to)) => {
-            if list_to.data_type() != list_from.data_type() {
-                // To transform inner type, can first cast to FSL with new 
inner type.
-                let fsl_to = DataType::FixedSizeList(list_to.clone(), *size);
-                let array = cast_with_options(array, &fsl_to, cast_options)?;
-                cast_fixed_size_list_to_list::<i64>(array.as_ref())
-            } else {
-                cast_fixed_size_list_to_list::<i64>(array)
-            }
-        }
-        (FixedSizeList(_, size_from), FixedSizeList(list_to, size_to)) => {
-            if size_from != size_to {
-                return Err(ArrowError::CastError(
-                    "cannot cast fixed-size-list to fixed-size-list with 
different size".into(),
-                ));
-            }
-            let array = 
array.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
-            let values = cast_with_options(array.values(), 
list_to.data_type(), cast_options)?;
-            Ok(Arc::new(FixedSizeListArray::try_new(
-                list_to.clone(),
-                *size_from,
-                values,
-                array.nulls().cloned(),
-            )?))
-        }
         (_, List(to)) => cast_values_to_list::<i32>(array, to, cast_options),
         (_, LargeList(to)) => cast_values_to_list::<i64>(array, to, 
cast_options),
+        (_, ListView(to)) => cast_values_to_list_view::<i32>(array, to, 
cast_options),
+        (_, LargeListView(to)) => cast_values_to_list_view::<i64>(array, to, 
cast_options),
         (_, FixedSizeList(to, size)) if *size == 1 => {
             cast_values_to_fixed_size_list(array, to, *size, cast_options)
         }
-        (FixedSizeList(_, size), _) if *size == 1 => {
-            cast_single_element_fixed_size_list_to_values(array, to_type, 
cast_options)
-        }
+        // Map
         (Map(_, ordered1), Map(_, ordered2)) if ordered1 == ordered2 => {
             cast_map_values(array.as_map(), to_type, cast_options, 
ordered1.to_owned())
         }
@@ -8831,14 +8852,14 @@ mod tests {
     #[test]
     fn test_can_cast_types_fixed_size_list_to_list() {
         // DataType::List
-        let array1 = Arc::new(make_fixed_size_list_array()) as ArrayRef;
+        let array1 = make_fixed_size_list_array();
         assert!(can_cast_types(
             array1.data_type(),
             &DataType::List(Arc::new(Field::new("", DataType::Int32, false)))
         ));
 
         // DataType::LargeList
-        let array2 = Arc::new(make_fixed_size_list_array_for_large_list()) as 
ArrayRef;
+        let array2 = make_fixed_size_list_array_for_large_list();
         assert!(can_cast_types(
             array2.data_type(),
             &DataType::LargeList(Arc::new(Field::new("", DataType::Int64, 
false)))
@@ -8849,7 +8870,7 @@ mod tests {
     fn test_cast_fixed_size_list_to_list() {
         // Important cases:
         // 1. With/without nulls
-        // 2. LargeList and List
+        // 2. List/LargeList/ListView/LargeListView
         // 3. With and without inner casts
 
         let cases = [
@@ -8897,6 +8918,48 @@ mod tests {
                     Some([Some(2), Some(2)]),
                 ])) as ArrayRef,
             ),
+            // fixed_size_list<i32, 2> => list_view<i32>
+            (
+                Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+                    [[1, 1].map(Some), [2, 2].map(Some)].map(Some),
+                    2,
+                )) as ArrayRef,
+                Arc::new(ListViewArray::from_iter_primitive::<Int32Type, _, 
_>([
+                    Some([Some(1), Some(1)]),
+                    Some([Some(2), Some(2)]),
+                ])) as ArrayRef,
+            ),
+            // fixed_size_list<i32, 2> => list_view<i32> (nullable)
+            (
+                Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+                    [None, Some([Some(2), Some(2)])],
+                    2,
+                )) as ArrayRef,
+                Arc::new(ListViewArray::from_iter_primitive::<Int32Type, _, 
_>([
+                    None,
+                    Some([Some(2), Some(2)]),
+                ])) as ArrayRef,
+            ),
+            // fixed_size_list<i32, 2> => large_list_view<i64>
+            (
+                Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+                    [[1, 1].map(Some), [2, 2].map(Some)].map(Some),
+                    2,
+                )) as ArrayRef,
+                Arc::new(LargeListViewArray::from_iter_primitive::<Int64Type, 
_, _>(
+                    [Some([Some(1), Some(1)]), Some([Some(2), Some(2)])],
+                )) as ArrayRef,
+            ),
+            // fixed_size_list<i32, 2> => large_list_view<i64> (nullable)
+            (
+                Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+                    [None, Some([Some(2), Some(2)])],
+                    2,
+                )) as ArrayRef,
+                Arc::new(LargeListViewArray::from_iter_primitive::<Int64Type, 
_, _>(
+                    [None, Some([Some(2), Some(2)])],
+                )) as ArrayRef,
+            ),
         ];
 
         for (array, expected) in cases {
@@ -9025,7 +9088,7 @@ mod tests {
     #[test]
     fn test_cast_list_containers() {
         // large-list to list
-        let array = Arc::new(make_large_list_array()) as ArrayRef;
+        let array = make_large_list_array();
         let list_array = cast(
             &array,
             &DataType::List(Arc::new(Field::new("", DataType::Int32, false))),
@@ -9039,7 +9102,7 @@ mod tests {
         assert_eq!(&expected.value(2), &actual.value(2));
 
         // list to large-list
-        let array = Arc::new(make_list_array()) as ArrayRef;
+        let array = make_list_array();
         let large_list_array = cast(
             &array,
             &DataType::LargeList(Arc::new(Field::new("", DataType::Int32, 
false))),
@@ -9056,6 +9119,80 @@ mod tests {
         assert_eq!(&expected.value(2), &actual.value(2));
     }
 
+    #[test]
+    fn test_cast_list_view() {
+        // cast between list view and list view
+        let array = make_list_view_array();
+        let to = DataType::ListView(Field::new_list_field(DataType::Float32, 
true).into());
+        assert!(can_cast_types(array.data_type(), &to));
+        let actual = cast(&array, &to).unwrap();
+        let actual = actual.as_list_view::<i32>();
+
+        assert_eq!(
+            &Float32Array::from(vec![0.0, 1.0, 2.0]) as &dyn Array,
+            actual.value(0).as_ref()
+        );
+        assert_eq!(
+            &Float32Array::from(vec![3.0, 4.0, 5.0]) as &dyn Array,
+            actual.value(1).as_ref()
+        );
+        assert_eq!(
+            &Float32Array::from(vec![6.0, 7.0]) as &dyn Array,
+            actual.value(2).as_ref()
+        );
+
+        // cast between large list view and large list view
+        let array = make_large_list_view_array();
+        let to = 
DataType::LargeListView(Field::new_list_field(DataType::Float32, true).into());
+        assert!(can_cast_types(array.data_type(), &to));
+        let actual = cast(&array, &to).unwrap();
+        let actual = actual.as_list_view::<i64>();
+
+        assert_eq!(
+            &Float32Array::from(vec![0.0, 1.0, 2.0]) as &dyn Array,
+            actual.value(0).as_ref()
+        );
+        assert_eq!(
+            &Float32Array::from(vec![3.0, 4.0, 5.0]) as &dyn Array,
+            actual.value(1).as_ref()
+        );
+        assert_eq!(
+            &Float32Array::from(vec![6.0, 7.0]) as &dyn Array,
+            actual.value(2).as_ref()
+        );
+    }
+
+    #[test]
+    fn test_non_list_to_list_view() {
+        let input = Arc::new(Int32Array::from(vec![Some(0), None, Some(2)])) 
as ArrayRef;
+        let expected_primitive =
+            Arc::new(Float32Array::from(vec![Some(0.0), None, Some(2.0)])) as 
ArrayRef;
+
+        // [[0], [NULL], [2]]
+        let expected = ListViewArray::new(
+            Field::new_list_field(DataType::Float32, true).into(),
+            vec![0, 1, 2].into(),
+            vec![1, 1, 1].into(),
+            expected_primitive.clone(),
+            None,
+        );
+        assert!(can_cast_types(input.data_type(), expected.data_type()));
+        let actual = cast(&input, expected.data_type()).unwrap();
+        assert_eq!(actual.as_ref(), &expected);
+
+        // [[0], [NULL], [2]]
+        let expected = LargeListViewArray::new(
+            Field::new_list_field(DataType::Float32, true).into(),
+            vec![0, 1, 2].into(),
+            vec![1, 1, 1].into(),
+            expected_primitive.clone(),
+            None,
+        );
+        assert!(can_cast_types(input.data_type(), expected.data_type()));
+        let actual = cast(&input, expected.data_type()).unwrap();
+        assert_eq!(actual.as_ref(), &expected);
+    }
+
     #[test]
     fn test_cast_list_to_fsl() {
         // There four noteworthy cases we should handle:
@@ -9127,6 +9264,82 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_cast_list_view_to_fsl() {
+        // There four noteworthy cases we should handle:
+        // 1. No nulls
+        // 2. Nulls that are always empty
+        // 3. Nulls that have varying lengths
+        // 4. Nulls that are correctly sized (same as target list size)
+
+        // Non-null case
+        let field = Arc::new(Field::new_list_field(DataType::Int32, true));
+        let values = vec![
+            Some(vec![Some(1), Some(2), Some(3)]),
+            Some(vec![Some(4), Some(5), Some(6)]),
+        ];
+        let array = Arc::new(ListViewArray::from_iter_primitive::<Int32Type, 
_, _>(
+            values.clone(),
+        )) as ArrayRef;
+        let expected = 
Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
+            values, 3,
+        )) as ArrayRef;
+        let actual = cast(array.as_ref(), 
&DataType::FixedSizeList(field.clone(), 3)).unwrap();
+        assert_eq!(expected.as_ref(), actual.as_ref());
+
+        // Null cases
+        // Array is [[1, 2, 3], null, [4, 5, 6], null]
+        let cases = [
+            (
+                // Zero-length nulls
+                vec![1, 2, 3, 4, 5, 6],
+                vec![0, 0, 3, 0],
+                vec![3, 0, 3, 0],
+            ),
+            (
+                // Varying-length nulls
+                vec![1, 2, 3, 0, 0, 4, 5, 6, 0],
+                vec![0, 1, 5, 0],
+                vec![3, 2, 3, 1],
+            ),
+            (
+                // Correctly-sized nulls
+                vec![1, 2, 3, 0, 0, 0, 4, 5, 6, 0, 0, 0],
+                vec![0, 3, 6, 9],
+                vec![3, 3, 3, 3],
+            ),
+            (
+                // Mixed nulls
+                vec![1, 2, 3, 4, 5, 6, 0, 0, 0],
+                vec![0, 0, 3, 6],
+                vec![3, 0, 3, 3],
+            ),
+        ];
+        let null_buffer = NullBuffer::from(vec![true, false, true, false]);
+
+        let expected = 
Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
+            vec![
+                Some(vec![Some(1), Some(2), Some(3)]),
+                None,
+                Some(vec![Some(4), Some(5), Some(6)]),
+                None,
+            ],
+            3,
+        )) as ArrayRef;
+
+        for (values, offsets, lengths) in cases.iter() {
+            let array = Arc::new(ListViewArray::new(
+                field.clone(),
+                offsets.clone().into(),
+                lengths.clone().into(),
+                Arc::new(Int32Array::from(values.clone())),
+                Some(null_buffer.clone()),
+            )) as ArrayRef;
+            let actual = cast(array.as_ref(), 
&DataType::FixedSizeList(field.clone(), 3)).unwrap();
+            assert_eq!(expected.as_ref(), actual.as_ref());
+        }
+    }
+
     #[test]
     fn test_cast_list_to_fsl_safety() {
         let values = vec![
@@ -9194,19 +9407,91 @@ mod tests {
     }
 
     #[test]
-    fn test_cast_large_list_to_fsl() {
-        let values = vec![Some(vec![Some(1), Some(2)]), Some(vec![Some(3), 
Some(4)])];
-        let array = Arc::new(LargeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+    fn test_cast_list_view_to_fsl_safety() {
+        let values = vec![
+            Some(vec![Some(1), Some(2), Some(3)]),
+            Some(vec![Some(4), Some(5)]),
+            Some(vec![Some(6), Some(7), Some(8), Some(9)]),
+            Some(vec![Some(3), Some(4), Some(5)]),
+        ];
+        let array = Arc::new(ListViewArray::from_iter_primitive::<Int32Type, 
_, _>(
             values.clone(),
         )) as ArrayRef;
+
+        let res = cast_with_options(
+            array.as_ref(),
+            
&DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, 
true)), 3),
+            &CastOptions {
+                safe: false,
+                ..Default::default()
+            },
+        );
+        assert!(res.is_err());
+        assert!(
+            format!("{res:?}")
+                .contains("Cannot cast to FixedSizeList(3): value at index 1 
has length 2")
+        );
+
+        // When safe=true (default), the cast will fill nulls for lists that 
are
+        // too short and truncate lists that are too long.
+        let res = cast(
+            array.as_ref(),
+            
&DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, 
true)), 3),
+        )
+        .unwrap();
         let expected = 
Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
-            values, 2,
+            vec![
+                Some(vec![Some(1), Some(2), Some(3)]),
+                None, // Too short -> replaced with null
+                None, // Too long -> replaced with null
+                Some(vec![Some(3), Some(4), Some(5)]),
+            ],
+            3,
         )) as ArrayRef;
-        let actual = cast(
+        assert_eq!(expected.as_ref(), res.as_ref());
+
+        // The safe option is false and the source array contains a null list.
+        // issue: https://github.com/apache/arrow-rs/issues/5642
+        let array = Arc::new(ListViewArray::from_iter_primitive::<Int32Type, 
_, _>(vec![
+            Some(vec![Some(1), Some(2), Some(3)]),
+            None,
+        ])) as ArrayRef;
+        let res = cast_with_options(
             array.as_ref(),
-            
&DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, 
true)), 2),
+            
&DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, 
true)), 3),
+            &CastOptions {
+                safe: false,
+                ..Default::default()
+            },
         )
         .unwrap();
+        let expected = 
Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
+            vec![Some(vec![Some(1), Some(2), Some(3)]), None],
+            3,
+        )) as ArrayRef;
+        assert_eq!(expected.as_ref(), res.as_ref());
+    }
+
+    #[test]
+    fn test_cast_large_list_to_fsl() {
+        let values = vec![Some(vec![Some(1), Some(2)]), Some(vec![Some(3), 
Some(4)])];
+        let expected = 
Arc::new(FixedSizeListArray::from_iter_primitive::<Int32Type, _, _>(
+            values.clone(),
+            2,
+        )) as ArrayRef;
+        let target_type =
+            
DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, true)), 
2);
+
+        let array = Arc::new(LargeListArray::from_iter_primitive::<Int32Type, 
_, _>(
+            values.clone(),
+        )) as ArrayRef;
+        let actual = cast(array.as_ref(), &target_type).unwrap();
+        assert_eq!(expected.as_ref(), actual.as_ref());
+
+        let array = 
Arc::new(LargeListViewArray::from_iter_primitive::<Int32Type, _, _>(
+            values.clone(),
+        )) as ArrayRef;
+        let actual = cast(array.as_ref(), &target_type).unwrap();
         assert_eq!(expected.as_ref(), actual.as_ref());
     }
 
@@ -9246,97 +9531,95 @@ mod tests {
 
     #[test]
     fn test_cast_list_to_fsl_empty() {
-        let field = Arc::new(Field::new_list_field(DataType::Int32, true));
-        let array = new_empty_array(&DataType::List(field.clone()));
-
-        let target_type = DataType::FixedSizeList(field.clone(), 3);
+        let inner_field = Arc::new(Field::new_list_field(DataType::Int32, 
true));
+        let target_type = DataType::FixedSizeList(inner_field.clone(), 3);
         let expected = new_empty_array(&target_type);
 
+        // list
+        let array = new_empty_array(&DataType::List(inner_field.clone()));
+        assert!(can_cast_types(array.data_type(), &target_type));
         let actual = cast(array.as_ref(), &target_type).unwrap();
         assert_eq!(expected.as_ref(), actual.as_ref());
-    }
 
-    fn make_list_array() -> ListArray {
-        // Construct a value array
-        let value_data = ArrayData::builder(DataType::Int32)
-            .len(8)
-            .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
-            .build()
-            .unwrap();
+        // largelist
+        let array = new_empty_array(&DataType::LargeList(inner_field.clone()));
+        assert!(can_cast_types(array.data_type(), &target_type));
+        let actual = cast(array.as_ref(), &target_type).unwrap();
+        assert_eq!(expected.as_ref(), actual.as_ref());
 
-        // Construct a buffer for value offsets, for the nested array:
-        //  [[0, 1, 2], [3, 4, 5], [6, 7]]
-        let value_offsets = Buffer::from_slice_ref([0, 3, 6, 8]);
+        // listview
+        let array = new_empty_array(&DataType::ListView(inner_field.clone()));
+        assert!(can_cast_types(array.data_type(), &target_type));
+        let actual = cast(array.as_ref(), &target_type).unwrap();
+        assert_eq!(expected.as_ref(), actual.as_ref());
 
-        // Construct a list array from the above two
-        let list_data_type = 
DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
-        let list_data = ArrayData::builder(list_data_type)
-            .len(3)
-            .add_buffer(value_offsets)
-            .add_child_data(value_data)
-            .build()
-            .unwrap();
-        ListArray::from(list_data)
+        // largelistview
+        let array = 
new_empty_array(&DataType::LargeListView(inner_field.clone()));
+        assert!(can_cast_types(array.data_type(), &target_type));
+        let actual = cast(array.as_ref(), &target_type).unwrap();
+        assert_eq!(expected.as_ref(), actual.as_ref());
     }
 
-    fn make_large_list_array() -> LargeListArray {
-        // Construct a value array
-        let value_data = ArrayData::builder(DataType::Int32)
-            .len(8)
-            .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
-            .build()
-            .unwrap();
-
-        // Construct a buffer for value offsets, for the nested array:
-        //  [[0, 1, 2], [3, 4, 5], [6, 7]]
-        let value_offsets = Buffer::from_slice_ref([0i64, 3, 6, 8]);
+    fn make_list_array() -> ArrayRef {
+        // [[0, 1, 2], [3, 4, 5], [6, 7]]
+        Arc::new(ListArray::new(
+            Field::new_list_field(DataType::Int32, true).into(),
+            OffsetBuffer::from_lengths(vec![3, 3, 2]),
+            Arc::new(Int32Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
+    }
 
-        // Construct a list array from the above two
-        let list_data_type =
-            
DataType::LargeList(Arc::new(Field::new_list_field(DataType::Int32, true)));
-        let list_data = ArrayData::builder(list_data_type)
-            .len(3)
-            .add_buffer(value_offsets)
-            .add_child_data(value_data)
-            .build()
-            .unwrap();
-        LargeListArray::from(list_data)
+    fn make_large_list_array() -> ArrayRef {
+        // [[0, 1, 2], [3, 4, 5], [6, 7]]
+        Arc::new(LargeListArray::new(
+            Field::new_list_field(DataType::Int32, true).into(),
+            OffsetBuffer::from_lengths(vec![3, 3, 2]),
+            Arc::new(Int32Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
     }
 
-    fn make_fixed_size_list_array() -> FixedSizeListArray {
-        // Construct a value array
-        let value_data = ArrayData::builder(DataType::Int32)
-            .len(8)
-            .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
-            .build()
-            .unwrap();
+    fn make_list_view_array() -> ArrayRef {
+        // [[0, 1, 2], [3, 4, 5], [6, 7]]
+        Arc::new(ListViewArray::new(
+            Field::new_list_field(DataType::Int32, true).into(),
+            vec![0, 3, 6].into(),
+            vec![3, 3, 2].into(),
+            Arc::new(Int32Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
+    }
 
-        let list_data_type =
-            
DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, true)), 
4);
-        let list_data = ArrayData::builder(list_data_type)
-            .len(2)
-            .add_child_data(value_data)
-            .build()
-            .unwrap();
-        FixedSizeListArray::from(list_data)
+    fn make_large_list_view_array() -> ArrayRef {
+        // [[0, 1, 2], [3, 4, 5], [6, 7]]
+        Arc::new(LargeListViewArray::new(
+            Field::new_list_field(DataType::Int32, true).into(),
+            vec![0, 3, 6].into(),
+            vec![3, 3, 2].into(),
+            Arc::new(Int32Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
     }
 
-    fn make_fixed_size_list_array_for_large_list() -> FixedSizeListArray {
-        // Construct a value array
-        let value_data = ArrayData::builder(DataType::Int64)
-            .len(8)
-            .add_buffer(Buffer::from_slice_ref([0i64, 1, 2, 3, 4, 5, 6, 7]))
-            .build()
-            .unwrap();
+    fn make_fixed_size_list_array() -> ArrayRef {
+        // [[0, 1, 2, 3], [4, 5, 6, 7]]
+        Arc::new(FixedSizeListArray::new(
+            Field::new_list_field(DataType::Int32, true).into(),
+            4,
+            Arc::new(Int32Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
+    }
 
-        let list_data_type =
-            
DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int64, true)), 
4);
-        let list_data = ArrayData::builder(list_data_type)
-            .len(2)
-            .add_child_data(value_data)
-            .build()
-            .unwrap();
-        FixedSizeListArray::from(list_data)
+    fn make_fixed_size_list_array_for_large_list() -> ArrayRef {
+        // [[0, 1, 2, 3], [4, 5, 6, 7]]
+        Arc::new(FixedSizeListArray::new(
+            Field::new_list_field(DataType::Int64, true).into(),
+            4,
+            Arc::new(Int64Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7])),
+            None,
+        ))
     }
 
     #[test]
@@ -9598,7 +9881,7 @@ mod tests {
     fn test_list_cast_offsets() {
         // test if offset of the array is taken into account during cast
         let array1 = make_list_array().slice(1, 2);
-        let array2 = Arc::new(make_list_array()) as ArrayRef;
+        let array2 = make_list_array();
 
         let dt = 
DataType::LargeList(Arc::new(Field::new_list_field(DataType::Int32, true)));
         let out1 = cast(&array1, &dt).unwrap();
@@ -9609,60 +9892,57 @@ mod tests {
 
     #[test]
     fn test_list_to_string() {
-        let str_array = StringArray::from(vec!["a", "b", "c", "d", "e", "f", 
"g", "h"]);
-        let value_offsets = Buffer::from_slice_ref([0, 3, 6, 8]);
-        let value_data = str_array.into_data();
+        fn assert_cast(array: &ArrayRef, expected: &[&str]) {
+            assert!(can_cast_types(array.data_type(), &DataType::Utf8));
+            let out = cast(array, &DataType::Utf8).unwrap();
+            let out = out
+                .as_string::<i32>()
+                .into_iter()
+                .flatten()
+                .collect::<Vec<_>>();
+            assert_eq!(out, expected);
 
-        let list_data_type = 
DataType::List(Arc::new(Field::new_list_field(DataType::Utf8, true)));
-        let list_data = ArrayData::builder(list_data_type)
-            .len(3)
-            .add_buffer(value_offsets)
-            .add_child_data(value_data)
-            .build()
-            .unwrap();
-        let array = Arc::new(ListArray::from(list_data)) as ArrayRef;
+            assert!(can_cast_types(array.data_type(), &DataType::LargeUtf8));
+            let out = cast(array, &DataType::LargeUtf8).unwrap();
+            let out = out
+                .as_string::<i64>()
+                .into_iter()
+                .flatten()
+                .collect::<Vec<_>>();
+            assert_eq!(out, expected);
 
-        let out = cast(&array, &DataType::Utf8).unwrap();
-        let out = out
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&out, &vec!["[a, b, c]", "[d, e, f]", "[g, h]"]);
+            assert!(can_cast_types(array.data_type(), &DataType::Utf8View));
+            let out = cast(array, &DataType::Utf8View).unwrap();
+            let out = out
+                .as_string_view()
+                .into_iter()
+                .flatten()
+                .collect::<Vec<_>>();
+            assert_eq!(out, expected);
+        }
 
-        let out = cast(&array, &DataType::LargeUtf8).unwrap();
-        let out = out
-            .as_any()
-            .downcast_ref::<LargeStringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&out, &vec!["[a, b, c]", "[d, e, f]", "[g, h]"]);
+        let array = Arc::new(ListArray::new(
+            Field::new_list_field(DataType::Utf8, true).into(),
+            OffsetBuffer::from_lengths(vec![3, 3, 2]),
+            Arc::new(StringArray::from(vec![
+                "a", "b", "c", "d", "e", "f", "g", "h",
+            ])),
+            None,
+        )) as ArrayRef;
 
-        let array = Arc::new(make_list_array()) as ArrayRef;
-        let out = cast(&array, &DataType::Utf8).unwrap();
-        let out = out
-            .as_any()
-            .downcast_ref::<StringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&out, &vec!["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
+        assert_cast(&array, &["[a, b, c]", "[d, e, f]", "[g, h]"]);
 
-        let array = Arc::new(make_large_list_array()) as ArrayRef;
-        let out = cast(&array, &DataType::LargeUtf8).unwrap();
-        let out = out
-            .as_any()
-            .downcast_ref::<LargeStringArray>()
-            .unwrap()
-            .into_iter()
-            .flatten()
-            .collect::<Vec<_>>();
-        assert_eq!(&out, &vec!["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
+        let array = make_list_array();
+        assert_cast(&array, &["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
+
+        let array = make_large_list_array();
+        assert_cast(&array, &["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
+
+        let array = make_list_view_array();
+        assert_cast(&array, &["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
+
+        let array = make_large_list_view_array();
+        assert_cast(&array, &["[0, 1, 2]", "[3, 4, 5]", "[6, 7]"]);
     }
 
     #[test]
@@ -12637,11 +12917,23 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
         let expected_list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
         assert_eq!(got_list, &expected_list);
     }
 
+    #[test]
+    fn test_cast_list_view_to_large_list() {
+        let list_view = ListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
+        let target_type = DataType::LargeList(Arc::new(Field::new("item", 
DataType::Int32, true)));
+        assert!(can_cast_types(list_view.data_type(), &target_type));
+        let cast_result = cast(&list_view, &target_type).unwrap();
+        let got_list = cast_result.as_list::<i64>();
+        let expected_list =
+            LargeListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
+        assert_eq!(got_list, &expected_list);
+    }
+
     #[test]
     fn test_cast_list_to_list_view() {
         let list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
@@ -12649,13 +12941,50 @@ mod tests {
         assert!(can_cast_types(list.data_type(), &target_type));
         let cast_result = cast(&list, &target_type).unwrap();
 
-        let got_list_view = cast_result
-            .as_any()
-            .downcast_ref::<ListViewArray>()
-            .unwrap();
+        let got_list_view = cast_result.as_list_view::<i32>();
         let expected_list_view =
             ListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
         assert_eq!(got_list_view, &expected_list_view);
+
+        // inner types get cast
+        let list = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
+            Some(vec![Some(1), Some(2)]),
+            None,
+            Some(vec![None, Some(3)]),
+        ]);
+        let target_type = DataType::ListView(Arc::new(Field::new("item", 
DataType::Float32, true)));
+        assert!(can_cast_types(list.data_type(), &target_type));
+        let cast_result = cast(&list, &target_type).unwrap();
+
+        let got_list_view = cast_result.as_list_view::<i32>();
+        let expected_list_view = 
ListViewArray::from_iter_primitive::<Float32Type, _, _>(vec![
+            Some(vec![Some(1.0), Some(2.0)]),
+            None,
+            Some(vec![None, Some(3.0)]),
+        ]);
+        assert_eq!(got_list_view, &expected_list_view);
+    }
+
+    #[test]
+    fn test_cast_list_to_large_list_view() {
+        let list = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
+            Some(vec![Some(1), Some(2)]),
+            None,
+            Some(vec![None, Some(3)]),
+        ]);
+        let target_type =
+            DataType::LargeListView(Arc::new(Field::new("item", 
DataType::Float32, true)));
+        assert!(can_cast_types(list.data_type(), &target_type));
+        let cast_result = cast(&list, &target_type).unwrap();
+
+        let got_list_view = cast_result.as_list_view::<i64>();
+        let expected_list_view =
+            LargeListViewArray::from_iter_primitive::<Float32Type, _, _>(vec![
+                Some(vec![Some(1.0), Some(2.0)]),
+                None,
+                Some(vec![None, Some(3.0)]),
+            ]);
+        assert_eq!(got_list_view, &expected_list_view);
     }
 
     #[test]
@@ -12665,16 +12994,26 @@ mod tests {
         let target_type = DataType::LargeList(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = cast_result
-            .as_any()
-            .downcast_ref::<LargeListArray>()
-            .unwrap();
+        let got_list = cast_result.as_list::<i64>();
 
         let expected_list =
             LargeListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
         assert_eq!(got_list, &expected_list);
     }
 
+    #[test]
+    fn test_cast_large_list_view_to_list() {
+        let list_view =
+            LargeListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
+        let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
+        assert!(can_cast_types(list_view.data_type(), &target_type));
+        let cast_result = cast(&list_view, &target_type).unwrap();
+        let got_list = cast_result.as_list::<i32>();
+
+        let expected_list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
+        assert_eq!(got_list, &expected_list);
+    }
+
     #[test]
     fn test_cast_large_list_to_large_list_view() {
         let list = LargeListArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
@@ -12683,13 +13022,50 @@ mod tests {
         assert!(can_cast_types(list.data_type(), &target_type));
         let cast_result = cast(&list, &target_type).unwrap();
 
-        let got_list_view = cast_result
-            .as_any()
-            .downcast_ref::<LargeListViewArray>()
-            .unwrap();
+        let got_list_view = cast_result.as_list_view::<i64>();
         let expected_list_view =
             LargeListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
         assert_eq!(got_list_view, &expected_list_view);
+
+        // inner types get cast
+        let list = LargeListArray::from_iter_primitive::<Int32Type, _, _>(vec![
+            Some(vec![Some(1), Some(2)]),
+            None,
+            Some(vec![None, Some(3)]),
+        ]);
+        let target_type =
+            DataType::LargeListView(Arc::new(Field::new("item", 
DataType::Float32, true)));
+        assert!(can_cast_types(list.data_type(), &target_type));
+        let cast_result = cast(&list, &target_type).unwrap();
+
+        let got_list_view = cast_result.as_list_view::<i64>();
+        let expected_list_view =
+            LargeListViewArray::from_iter_primitive::<Float32Type, _, _>(vec![
+                Some(vec![Some(1.0), Some(2.0)]),
+                None,
+                Some(vec![None, Some(3.0)]),
+            ]);
+        assert_eq!(got_list_view, &expected_list_view);
+    }
+
+    #[test]
+    fn test_cast_large_list_to_list_view() {
+        let list = LargeListArray::from_iter_primitive::<Int32Type, _, _>(vec![
+            Some(vec![Some(1), Some(2)]),
+            None,
+            Some(vec![None, Some(3)]),
+        ]);
+        let target_type = DataType::ListView(Arc::new(Field::new("item", 
DataType::Float32, true)));
+        assert!(can_cast_types(list.data_type(), &target_type));
+        let cast_result = cast(&list, &target_type).unwrap();
+
+        let got_list_view = cast_result.as_list_view::<i32>();
+        let expected_list_view = 
ListViewArray::from_iter_primitive::<Float32Type, _, _>(vec![
+            Some(vec![Some(1.0), Some(2.0)]),
+            None,
+            Some(vec![None, Some(3.0)]),
+        ]);
+        assert_eq!(got_list_view, &expected_list_view);
     }
 
     #[test]
@@ -12704,7 +13080,7 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
         let expected_list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(vec![
             Some(vec![Some(1), Some(2), Some(3)]),
             Some(vec![Some(7), Some(8), Some(9)]),
@@ -12725,7 +13101,7 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
         let expected_list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(vec![
             Some(vec![Some(1)]),
             Some(vec![Some(1), Some(2)]),
@@ -12740,7 +13116,7 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
         let expected_list = ListArray::from_iter_primitive::<Int32Type, _, 
_>(values);
         assert_eq!(got_list, &expected_list);
     }
@@ -12752,7 +13128,7 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int64, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
 
         let expected_list =
             ListArray::from_iter_primitive::<Int64Type, _, 
_>(values.into_iter().map(|list| {
@@ -12777,7 +13153,7 @@ mod tests {
         let target_type = DataType::List(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got_list = 
cast_result.as_any().downcast_ref::<ListArray>().unwrap();
+        let got_list = cast_result.as_list::<i32>();
         let expected_list = ListArray::new(
             Arc::new(Field::new("item", DataType::Int32, true)),
             OffsetBuffer::from_lengths([3, 3, 3]),
@@ -12794,10 +13170,7 @@ mod tests {
             DataType::LargeListView(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got = cast_result
-            .as_any()
-            .downcast_ref::<LargeListViewArray>()
-            .unwrap();
+        let got = cast_result.as_list_view::<i64>();
 
         let expected =
             LargeListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
@@ -12811,10 +13184,7 @@ mod tests {
         let target_type = DataType::ListView(Arc::new(Field::new("item", 
DataType::Int32, true)));
         assert!(can_cast_types(list_view.data_type(), &target_type));
         let cast_result = cast(&list_view, &target_type).unwrap();
-        let got = cast_result
-            .as_any()
-            .downcast_ref::<ListViewArray>()
-            .unwrap();
+        let got = cast_result.as_list_view::<i32>();
 
         let expected = ListViewArray::from_iter_primitive::<Int32Type, _, 
_>(int32_list_values());
         assert_eq!(got, &expected);

Reply via email to