use crate::cast::*;
pub(crate) fn cast_values_to_list<O: OffsetSizeTrait>(
array: &dyn Array,
to: &FieldRef,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError> {
let values = cast_with_options(array, to.data_type(), cast_options)?;
let offsets = OffsetBuffer::from_lengths(std::iter::repeat(1).take(values.len()));
let list = GenericListArray::<O>::new(to.clone(), offsets, values, None);
Ok(Arc::new(list))
}
pub(crate) fn cast_values_to_fixed_size_list(
array: &dyn Array,
to: &FieldRef,
size: i32,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError> {
let values = cast_with_options(array, to.data_type(), cast_options)?;
let list = FixedSizeListArray::new(to.clone(), size, values, None);
Ok(Arc::new(list))
}
pub(crate) fn cast_single_element_fixed_size_list_to_values(
array: &dyn Array,
to: &DataType,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError> {
let values = array.as_fixed_size_list().values();
cast_with_options(values, to, cast_options)
}
pub(crate) fn cast_fixed_size_list_to_list<OffsetSize>(
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))
}
pub(crate) fn cast_list_to_fixed_size_list<OffsetSize>(
array: &GenericListArray<OffsetSize>,
field: &FieldRef,
size: i32,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError>
where
OffsetSize: OffsetSizeTrait,
{
let cap = array.len() * size as usize;
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
});
let values = array.values().to_data();
let mut mutable = MutableArrayData::new(vec![&values], nullable, cap);
let mut last_pos = 0;
for (idx, w) in array.offsets().windows(2).enumerate() {
let start_pos = w[0].as_usize();
let end_pos = w[1].as_usize();
let len = end_pos - start_pos;
if len != size as usize {
if cast_options.safe || array.is_null(idx) {
if last_pos != start_pos {
mutable.extend(0, last_pos, start_pos);
}
mutable.extend_nulls(size as _);
nulls.as_mut().unwrap().set_bit(idx, false);
last_pos = end_pos
} else {
return Err(ArrowError::CastError(format!(
"Cannot cast to FixedSizeList({size}): value at index {idx} has length {len}",
)));
}
}
}
let values = match last_pos {
0 => array.values().slice(0, cap), _ => {
if mutable.len() != cap {
let remaining = cap - mutable.len();
mutable.extend(0, last_pos, last_pos + remaining)
}
make_array(mutable.freeze())
}
};
let values = cast_with_options(values.as_ref(), field.data_type(), cast_options)?;
let nulls = nulls.map(|mut x| x.finish().into());
let array = FixedSizeListArray::new(field.clone(), size, values, nulls);
Ok(Arc::new(array))
}
pub(crate) fn cast_list_values<O: OffsetSizeTrait>(
array: &dyn Array,
to: &FieldRef,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError> {
let list = array.as_list::<O>();
let values = cast_with_options(list.values(), to.data_type(), cast_options)?;
Ok(Arc::new(GenericListArray::<O>::new(
to.clone(),
list.offsets().clone(),
values,
list.nulls().cloned(),
)))
}
pub(crate) fn cast_list<I: OffsetSizeTrait, O: OffsetSizeTrait>(
array: &dyn Array,
field: &FieldRef,
cast_options: &CastOptions,
) -> Result<ArrayRef, ArrowError> {
let list = array.as_list::<I>();
let values = list.values();
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(),
));
}
let values = cast_with_options(values, field.data_type(), cast_options)?;
let offsets: Vec<_> = offsets.iter().map(|x| O::usize_as(x.as_usize())).collect();
let offsets = unsafe { OffsetBuffer::new_unchecked(offsets.into()) };
Ok(Arc::new(GenericListArray::<O>::new(
field.clone(),
offsets,
values,
nulls,
)))
}