1use crate::{
2 bitmap::Bitmap,
3 datatypes::{DataType, Field},
4 error::Error,
5 offset::OffsetsBuffer,
6};
7
8use super::{new_empty_array, specification::try_check_offsets_bounds, Array};
9
10#[cfg(feature = "arrow")]
11mod data;
12mod ffi;
13pub(super) mod fmt;
14mod iterator;
15pub use iterator::*;
16
17#[derive(Clone)]
19pub struct MapArray {
20 data_type: DataType,
21 offsets: OffsetsBuffer<i32>,
23 field: Box<dyn Array>,
24 validity: Option<Bitmap>,
26}
27
28impl MapArray {
29 pub fn try_new(
37 data_type: DataType,
38 offsets: OffsetsBuffer<i32>,
39 field: Box<dyn Array>,
40 validity: Option<Bitmap>,
41 ) -> Result<Self, Error> {
42 try_check_offsets_bounds(&offsets, field.len())?;
43
44 let inner_field = Self::try_get_field(&data_type)?;
45 if let DataType::Struct(inner) = inner_field.data_type() {
46 if inner.len() != 2 {
47 return Err(Error::InvalidArgumentError(
48 "MapArray's inner `Struct` must have 2 fields (keys and maps)".to_string(),
49 ));
50 }
51 } else {
52 return Err(Error::InvalidArgumentError(
53 "MapArray expects `DataType::Struct` as its inner logical type".to_string(),
54 ));
55 }
56 if field.data_type() != inner_field.data_type() {
57 return Err(Error::InvalidArgumentError(
58 "MapArray expects `field.data_type` to match its inner DataType".to_string(),
59 ));
60 }
61
62 if validity
63 .as_ref()
64 .map_or(false, |validity| validity.len() != offsets.len_proxy())
65 {
66 return Err(Error::oos(
67 "validity mask length must match the number of values",
68 ));
69 }
70
71 Ok(Self {
72 data_type,
73 field,
74 offsets,
75 validity,
76 })
77 }
78
79 pub fn new(
85 data_type: DataType,
86 offsets: OffsetsBuffer<i32>,
87 field: Box<dyn Array>,
88 validity: Option<Bitmap>,
89 ) -> Self {
90 Self::try_new(data_type, offsets, field, validity).unwrap()
91 }
92
93 pub fn new_null(data_type: DataType, length: usize) -> Self {
95 let field = new_empty_array(Self::get_field(&data_type).data_type().clone());
96 Self::new(
97 data_type,
98 vec![0i32; 1 + length].try_into().unwrap(),
99 field,
100 Some(Bitmap::new_zeroed(length)),
101 )
102 }
103
104 pub fn new_empty(data_type: DataType) -> Self {
106 let field = new_empty_array(Self::get_field(&data_type).data_type().clone());
107 Self::new(data_type, OffsetsBuffer::default(), field, None)
108 }
109}
110
111impl MapArray {
112 pub fn slice(&mut self, offset: usize, length: usize) {
116 assert!(
117 offset + length <= self.len(),
118 "the offset of the new Buffer cannot exceed the existing length"
119 );
120 unsafe { self.slice_unchecked(offset, length) }
121 }
122
123 #[inline]
127 pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
128 self.validity.as_mut().and_then(|bitmap| {
129 bitmap.slice_unchecked(offset, length);
130 (bitmap.unset_bits() > 0).then(|| bitmap)
131 });
132 self.offsets.slice_unchecked(offset, length + 1);
133 }
134
135 impl_sliced!();
136 impl_mut_validity!();
137 impl_into_array!();
138
139 pub(crate) fn try_get_field(data_type: &DataType) -> Result<&Field, Error> {
140 if let DataType::Map(field, _) = data_type.to_logical_type() {
141 Ok(field.as_ref())
142 } else {
143 Err(Error::oos(
144 "The data_type's logical type must be DataType::Map",
145 ))
146 }
147 }
148
149 pub(crate) fn get_field(data_type: &DataType) -> &Field {
150 Self::try_get_field(data_type).unwrap()
151 }
152}
153
154impl MapArray {
156 #[inline]
158 pub fn len(&self) -> usize {
159 self.offsets.len_proxy()
160 }
161
162 #[inline]
164 pub fn offsets(&self) -> &OffsetsBuffer<i32> {
165 &self.offsets
166 }
167
168 #[inline]
170 pub fn field(&self) -> &Box<dyn Array> {
171 &self.field
172 }
173
174 #[inline]
176 pub fn value(&self, i: usize) -> Box<dyn Array> {
177 assert!(i < self.len());
178 unsafe { self.value_unchecked(i) }
179 }
180
181 #[inline]
185 pub unsafe fn value_unchecked(&self, i: usize) -> Box<dyn Array> {
186 let (start, end) = self.offsets.start_end_unchecked(i);
188 let length = end - start;
189
190 self.field.sliced_unchecked(start, length)
192 }
193}
194
195impl Array for MapArray {
196 impl_common_array!();
197
198 fn validity(&self) -> Option<&Bitmap> {
199 self.validity.as_ref()
200 }
201
202 #[inline]
203 fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
204 Box::new(self.clone().with_validity(validity))
205 }
206}