Skip to main content

arrow_cast/cast/
map.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::cast::*;
6
7/// Helper function that takes a map container and casts the inner datatype.
8pub(crate) fn cast_map_values(
9    from: &MapArray,
10    to_data_type: &DataType,
11    cast_options: &CastOptions,
12    to_ordered: bool,
13) -> Result<ArrayRef, ArrowError> {
14    let DataType::Map(entries_field, _) = to_data_type else {
15        unreachable!("cast_with_options only calls cast_map_values for Map target types");
16    };
17
18    let key_field = key_field(entries_field).ok_or(ArrowError::CastError(
19        "map is missing key field".to_string(),
20    ))?;
21    let value_field = value_field(entries_field).ok_or(ArrowError::CastError(
22        "map is missing value field".to_string(),
23    ))?;
24
25    let offsets = from.offsets();
26    let first = offsets.first();
27    // Only the entries that the offsets refer to, which excludes entries outside a slice
28    let entries = from
29        .entries()
30        .slice(first.as_usize(), (offsets.last() - first).as_usize());
31    let key_array = cast_with_options(entries.column(0), key_field.data_type(), cast_options)?;
32    let value_array = cast_with_options(entries.column(1), value_field.data_type(), cast_options)?;
33
34    Ok(Arc::new(MapArray::try_new(
35        entries_field.clone(),
36        offsets.clone().subtract(first),
37        StructArray::try_new(
38            Fields::from(vec![key_field, value_field]),
39            vec![key_array, value_array],
40            entries.nulls().cloned(),
41        )?,
42        from.nulls().cloned(),
43        to_ordered,
44    )?))
45}
46
47/// Gets the key field from the entries of a map.  For all other types returns None.
48pub(crate) fn key_field(entries_field: &FieldRef) -> Option<FieldRef> {
49    if let DataType::Struct(fields) = entries_field.data_type() {
50        fields.first().cloned()
51    } else {
52        None
53    }
54}
55
56/// Gets the value field from the entries of a map.  For all other types returns None.
57pub(crate) fn value_field(entries_field: &FieldRef) -> Option<FieldRef> {
58    if let DataType::Struct(fields) = entries_field.data_type() {
59        fields.get(1).cloned()
60    } else {
61        None
62    }
63}