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