vortex_array/arrays/map/
array.rs1use std::fmt::Display;
5use std::fmt::Formatter;
6use std::hash::Hasher;
7use std::sync::Arc;
8
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_ensure;
12
13use crate::ArrayEq;
14use crate::ArrayHash;
15use crate::ArrayRef;
16use crate::ArraySlots;
17use crate::EqMode;
18use crate::IntoArray;
19use crate::array::Array;
20use crate::array::ArrayParts;
21use crate::array::TypedArrayRef;
22use crate::array_slots;
23use crate::arrays::ListView;
24use crate::arrays::ListViewArray;
25use crate::arrays::listview::ListViewArrayExt;
26use crate::arrays::map::Map;
27use crate::dtype::DType;
28use crate::dtype::MapDType;
29use crate::validity::Validity;
30
31#[array_slots(Map)]
32pub struct MapSlots {
33 #[slot(0)]
35 pub entries: ArrayRef,
36}
37
38#[derive(Clone, Debug, Default)]
43pub struct MapData;
44
45impl Display for MapData {
46 fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
47 Ok(())
48 }
49}
50
51impl ArrayEq for MapData {
52 fn array_eq(&self, _other: &Self, _accuracy: EqMode) -> bool {
53 true
54 }
55}
56
57impl ArrayHash for MapData {
58 fn array_hash<H: Hasher>(&self, _state: &mut H, _accuracy: EqMode) {}
59}
60
61impl MapData {
62 pub(crate) fn make_slots(entries: ArrayRef) -> ArraySlots {
63 MapSlots { entries }.into_slots()
64 }
65}
66
67pub struct MapDataParts {
69 pub map_dtype: MapDType,
71 pub entries: ListViewArray,
73}
74
75pub trait MapArrayExt: MapArraySlotsExt {
77 fn entries_at(&self, index: usize) -> VortexResult<ArrayRef> {
79 self.entries().as_::<ListView>().list_elements_at(index)
80 }
81
82 fn entry_count_at(&self, index: usize) -> usize {
84 self.entries().as_::<ListView>().size_at(index)
85 }
86
87 fn map_validity(&self) -> Validity {
89 self.entries().as_::<ListView>().listview_validity()
90 }
91
92 fn map_dtype(&self) -> &MapDType {
94 self.as_ref()
95 .dtype()
96 .as_map_opt()
97 .vortex_expect("MapArray requires a map dtype")
98 }
99
100 fn keys_sorted(&self) -> bool {
102 self.map_dtype().keys_sorted()
103 }
104}
105impl<T: TypedArrayRef<Map>> MapArrayExt for T {}
106
107impl Array<Map> {
108 pub fn new(map_dtype: MapDType, entries: ListViewArray) -> Self {
115 Self::try_new(map_dtype, entries).vortex_expect("MapArray construction failed")
116 }
117
118 pub fn try_new(map_dtype: MapDType, entries: ListViewArray) -> VortexResult<Self> {
125 let nullability = entries.nullability();
126 let dtype = DType::Map(map_dtype, nullability);
127 let len = entries.len();
128 let slots = MapData::make_slots(entries.into_array());
129 let parts = ArrayParts::new(Map, dtype, len, MapData).with_slots(slots);
130 Self::try_from_parts(parts)
131 }
132
133 pub unsafe fn new_unchecked(map_dtype: MapDType, entries: ListViewArray) -> Self {
141 let nullability = entries.nullability();
142 let dtype = DType::Map(map_dtype, nullability);
143 let len = entries.len();
144 let slots = MapData::make_slots(entries.into_array());
145 let parts = ArrayParts::new(Map, dtype, len, MapData).with_slots(slots);
146 unsafe { Self::from_parts_unchecked(parts) }
147 }
148
149 pub fn into_data_parts(self) -> MapDataParts {
151 let map_dtype = self
152 .dtype()
153 .as_map_opt()
154 .vortex_expect("MapArray requires a map dtype")
155 .clone();
156 let entries = self.entries().clone().downcast::<ListView>();
157 MapDataParts { map_dtype, entries }
158 }
159}
160
161fn expected_entries_dtype(map_dtype: &MapDType, nullability: crate::dtype::Nullability) -> DType {
162 DType::List(Arc::new(map_dtype.entries_dtype()), nullability)
163}
164
165pub(super) fn validate_entries(
166 map_dtype: &MapDType,
167 nullability: crate::dtype::Nullability,
168 len: usize,
169 entries: &ArrayRef,
170) -> VortexResult<()> {
171 vortex_ensure!(
172 entries.is::<ListView>(),
173 "MapArray entries must use vortex.listview encoding, got {}",
174 entries.encoding_id()
175 );
176 vortex_ensure!(
177 entries.len() == len,
178 "MapArray entries length {} does not match outer length {len}",
179 entries.len()
180 );
181
182 let expected_dtype = expected_entries_dtype(map_dtype, nullability);
183 vortex_ensure!(
184 entries.dtype() == &expected_dtype,
185 "MapArray entries dtype {} does not match expected {expected_dtype}",
186 entries.dtype()
187 );
188
189 Ok(())
190}