Skip to main content

typed_arrow/bridge/
map.rs

1//! `Map` and `OrderedMap` bindings.
2
3use std::{collections::BTreeMap, sync::Arc};
4
5use arrow_array::{MapArray, builder::MapBuilder};
6use arrow_schema::{DataType, Field};
7
8use super::ArrowBinding;
9
10/// Wrapper denoting an Arrow `MapArray` column with entries `(K, V)`.
11///
12/// - Keys are non-nullable by Arrow spec.
13/// - Values are non-nullable for `Map<K, V, SORTED>` and nullable for `Map<K, Option<V>, SORTED>`.
14/// - Column-level nullability is expressed with `Option<Map<...>>`.
15#[derive(Debug, Clone, PartialEq)]
16pub struct Map<K, V, const SORTED: bool = false>(Vec<(K, V)>);
17
18impl<K, V, const SORTED: bool> Map<K, V, SORTED> {
19    /// Construct a new map from a vector of `(key, value)` pairs.
20    #[inline]
21    #[must_use]
22    pub fn new(entries: Vec<(K, V)>) -> Self {
23        Self(entries)
24    }
25    /// Borrow the underlying `(key, value)` entries.
26    #[inline]
27    #[must_use]
28    pub fn entries(&self) -> &Vec<(K, V)> {
29        &self.0
30    }
31    /// Consume and return the underlying `(key, value)` entries.
32    #[inline]
33    #[must_use]
34    pub fn into_inner(self) -> Vec<(K, V)> {
35        self.0
36    }
37}
38
39// Serialize/Deserialize implementation forwards to that for Vec<(K, V)>.
40#[cfg(feature = "serde")]
41impl<'de, K, V, const SORTED: bool> serde::de::Deserialize<'de> for Map<K, V, SORTED>
42where
43    K: serde::de::Deserialize<'de>,
44    V: serde::de::Deserialize<'de>,
45{
46    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47    where
48        D: serde::de::Deserializer<'de>,
49    {
50        Ok(Vec::<(K, V)>::deserialize(deserializer)?.into())
51    }
52}
53
54#[cfg(feature = "serde")]
55impl<K, V, const SORTED: bool> serde::Serialize for Map<K, V, SORTED>
56where
57    K: serde::Serialize,
58    V: serde::Serialize,
59{
60    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
61        self.0.serialize(serializer)
62    }
63}
64
65impl<K, V, const SORTED: bool> From<Vec<(K, V)>> for Map<K, V, SORTED> {
66    /// Convert a vector of `(key, value)` pairs into a `Map`.
67    #[inline]
68    fn from(entries: Vec<(K, V)>) -> Self {
69        Self::new(entries)
70    }
71}
72
73impl<K, V, const SORTED: bool> std::iter::FromIterator<(K, V)> for Map<K, V, SORTED> {
74    /// Collect an iterator of `(key, value)` pairs into a `Map`.
75    #[inline]
76    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
77        Self::new(iter.into_iter().collect())
78    }
79}
80
81impl<K, V, const SORTED: bool> ArrowBinding for Map<K, V, SORTED>
82where
83    K: ArrowBinding,
84    V: ArrowBinding,
85    <K as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
86    <V as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
87{
88    type Builder = MapBuilder<<K as ArrowBinding>::Builder, <V as ArrowBinding>::Builder>;
89    type Array = MapArray;
90    fn data_type() -> DataType {
91        let key_f = Field::new("keys", <K as ArrowBinding>::data_type(), false);
92        // MapBuilder names children `keys` and `values`; value field is nullable
93        let val_f = Field::new("values", <V as ArrowBinding>::data_type(), true);
94        let entries = DataType::Struct(vec![Arc::new(key_f), Arc::new(val_f)].into());
95        DataType::Map(Field::new("entries", entries, false).into(), SORTED)
96    }
97    fn new_builder(_capacity: usize) -> Self::Builder {
98        let kb = <K as ArrowBinding>::new_builder(0);
99        let vb = <V as ArrowBinding>::new_builder(0);
100        MapBuilder::new(None, kb, vb)
101    }
102    fn append_value(b: &mut Self::Builder, v: &Self) {
103        for (k, val) in &v.0 {
104            <K as ArrowBinding>::append_value(b.keys(), k);
105            <V as ArrowBinding>::append_value(b.values(), val);
106        }
107        let _ = b.append(true);
108    }
109    fn append_null(b: &mut Self::Builder) {
110        let _ = b.append(false);
111    }
112    fn finish(mut b: Self::Builder) -> Self::Array {
113        b.finish()
114    }
115}
116
117// Provide ArrowBinding for value-nullable variant via Option<V>
118impl<K, V, const SORTED: bool> ArrowBinding for Map<K, Option<V>, SORTED>
119where
120    K: ArrowBinding,
121    V: ArrowBinding,
122    <K as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
123    <V as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
124{
125    type Builder = MapBuilder<<K as ArrowBinding>::Builder, <V as ArrowBinding>::Builder>;
126    type Array = MapArray;
127    fn data_type() -> DataType {
128        let key_f = Field::new("keys", <K as ArrowBinding>::data_type(), false);
129        let val_f = Field::new("values", <V as ArrowBinding>::data_type(), true);
130        let entries = DataType::Struct(vec![Arc::new(key_f), Arc::new(val_f)].into());
131        DataType::Map(Field::new("entries", entries, false).into(), SORTED)
132    }
133    fn new_builder(_capacity: usize) -> Self::Builder {
134        let kb = <K as ArrowBinding>::new_builder(0);
135        let vb = <V as ArrowBinding>::new_builder(0);
136        MapBuilder::new(None, kb, vb)
137    }
138    fn append_value(b: &mut Self::Builder, v: &Self) {
139        for (k, val_opt) in &v.0 {
140            <K as ArrowBinding>::append_value(b.keys(), k);
141            match val_opt {
142                Some(val) => <V as ArrowBinding>::append_value(b.values(), val),
143                None => <V as ArrowBinding>::append_null(b.values()),
144            }
145        }
146        let _ = b.append(true);
147    }
148    fn append_null(b: &mut Self::Builder) {
149        let _ = b.append(false);
150    }
151    fn finish(mut b: Self::Builder) -> Self::Array {
152        b.finish()
153    }
154}
155
156/// Sorted-keys `Map`: entries sourced from `BTreeMap<K, V>`, declaring `keys_sorted = true`.
157/// Keys are non-nullable; the value field is nullable per `MapBuilder` semantics, but this
158/// wrapper does not write null values.
159#[derive(Debug, Clone, PartialEq)]
160pub struct OrderedMap<K, V>(BTreeMap<K, V>);
161
162// Serialize/Deserialize implementation forwards to that for BTreeMap<K, V>.
163#[cfg(feature = "serde")]
164impl<'de, K, V> serde::de::Deserialize<'de> for OrderedMap<K, V>
165where
166    K: serde::de::Deserialize<'de> + Ord,
167    V: serde::de::Deserialize<'de>,
168{
169    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
170    where
171        D: serde::de::Deserializer<'de>,
172    {
173        Ok(Self(BTreeMap::deserialize(deserializer)?))
174    }
175}
176
177#[cfg(feature = "serde")]
178impl<K, V> serde::Serialize for OrderedMap<K, V>
179where
180    K: serde::Serialize,
181    V: serde::Serialize,
182{
183    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
184        self.0.serialize(serializer)
185    }
186}
187
188impl<K, V> OrderedMap<K, V> {
189    /// Construct a new ordered-map from a `BTreeMap` (keys sorted).
190    #[inline]
191    #[must_use]
192    pub fn new(map: BTreeMap<K, V>) -> Self {
193        Self(map)
194    }
195    /// Borrow the underlying `BTreeMap`.
196    #[inline]
197    #[must_use]
198    pub fn map(&self) -> &BTreeMap<K, V> {
199        &self.0
200    }
201    /// Consume and return the underlying `BTreeMap`.
202    #[inline]
203    #[must_use]
204    pub fn into_inner(self) -> BTreeMap<K, V> {
205        self.0
206    }
207}
208
209impl<K, V> ArrowBinding for OrderedMap<K, V>
210where
211    K: ArrowBinding + Ord,
212    V: ArrowBinding,
213    <K as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
214    <V as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
215{
216    type Builder = MapBuilder<<K as ArrowBinding>::Builder, <V as ArrowBinding>::Builder>;
217    type Array = MapArray;
218    fn data_type() -> DataType {
219        let key_f = Field::new("keys", <K as ArrowBinding>::data_type(), false);
220        let val_f = Field::new("values", <V as ArrowBinding>::data_type(), true);
221        let entries = DataType::Struct(vec![Arc::new(key_f), Arc::new(val_f)].into());
222        DataType::Map(Field::new("entries", entries, false).into(), true)
223    }
224    fn new_builder(_capacity: usize) -> Self::Builder {
225        let kb = <K as ArrowBinding>::new_builder(0);
226        let vb = <V as ArrowBinding>::new_builder(0);
227        MapBuilder::new(None, kb, vb)
228    }
229    fn append_value(b: &mut Self::Builder, v: &Self) {
230        for (k, val) in &v.0 {
231            <K as ArrowBinding>::append_value(b.keys(), k);
232            <V as ArrowBinding>::append_value(b.values(), val);
233        }
234        let _ = b.append(true);
235    }
236    fn append_null(b: &mut Self::Builder) {
237        let _ = b.append(false);
238    }
239    fn finish(mut b: Self::Builder) -> Self::Array {
240        use arrow_array::Array;
241        use arrow_data::ArrayData;
242
243        let map_array = b.finish();
244
245        // MapBuilder always creates maps with sorted=false, so we need to manually update it
246        // Get the existing field and create a new DataType with sorted=true
247        let data = map_array.into_data();
248        let (field, _sorted) = match data.data_type() {
249            DataType::Map(f, _) => (f.clone(), true),
250            _ => unreachable!(),
251        };
252
253        // Reconstruct the MapArray with sorted=true flag
254        // All data is copied from the valid MapArray produced by MapBuilder
255        let new_data = ArrayData::builder(DataType::Map(field, true))
256            .len(data.len())
257            .buffers(data.buffers().to_vec())
258            .child_data(data.child_data().to_vec())
259            .nulls(data.nulls().cloned())
260            .build()
261            .expect("MapArray reconstruction should succeed - all data copied from valid array");
262
263        MapArray::from(new_data)
264    }
265}
266
267// Provide ArrowBinding for OrderedMap<K, Option<V>> mirroring the non-wrapper variant
268impl<K, V> ArrowBinding for OrderedMap<K, Option<V>>
269where
270    K: ArrowBinding + Ord,
271    V: ArrowBinding,
272    <K as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
273    <V as ArrowBinding>::Builder: arrow_array::builder::ArrayBuilder,
274{
275    type Builder = MapBuilder<<K as ArrowBinding>::Builder, <V as ArrowBinding>::Builder>;
276    type Array = MapArray;
277    fn data_type() -> DataType {
278        let key_f = Field::new("keys", <K as ArrowBinding>::data_type(), false);
279        let val_f = Field::new("values", <V as ArrowBinding>::data_type(), true);
280        let entries = DataType::Struct(vec![Arc::new(key_f), Arc::new(val_f)].into());
281        DataType::Map(Field::new("entries", entries, false).into(), true)
282    }
283    fn new_builder(_capacity: usize) -> Self::Builder {
284        let kb = <K as ArrowBinding>::new_builder(0);
285        let vb = <V as ArrowBinding>::new_builder(0);
286        MapBuilder::new(None, kb, vb)
287    }
288    fn append_value(b: &mut Self::Builder, v: &Self) {
289        for (k, val_opt) in &v.0 {
290            <K as ArrowBinding>::append_value(b.keys(), k);
291            match val_opt {
292                Some(val) => <V as ArrowBinding>::append_value(b.values(), val),
293                None => <V as ArrowBinding>::append_null(b.values()),
294            }
295        }
296        let _ = b.append(true);
297    }
298    fn append_null(b: &mut Self::Builder) {
299        let _ = b.append(false);
300    }
301    fn finish(mut b: Self::Builder) -> Self::Array {
302        use arrow_array::Array;
303        use arrow_data::ArrayData;
304
305        let map_array = b.finish();
306
307        // MapBuilder always creates maps with sorted=false, so we need to manually update it
308        // Get the existing field and create a new DataType with sorted=true
309        let data = map_array.into_data();
310        let (field, _sorted) = match data.data_type() {
311            DataType::Map(f, _) => (f.clone(), true),
312            _ => unreachable!(),
313        };
314
315        // Reconstruct the MapArray with sorted=true flag
316        // All data is copied from the valid MapArray produced by MapBuilder
317        let new_data = ArrayData::builder(DataType::Map(field, true))
318            .len(data.len())
319            .buffers(data.buffers().to_vec())
320            .child_data(data.child_data().to_vec())
321            .nulls(data.nulls().cloned())
322            .build()
323            .expect("MapArray reconstruction should succeed - all data copied from valid array");
324
325        MapArray::from(new_data)
326    }
327}
328
329/// Iterator over views of map entries (key-value pairs).
330#[cfg(feature = "views")]
331pub struct MapView<'a, K, V, const SORTED: bool = false>
332where
333    K: super::ArrowBindingView + 'static,
334    V: super::ArrowBindingView + 'static,
335{
336    keys_array: &'a <K as super::ArrowBindingView>::Array,
337    values_array: &'a <V as super::ArrowBindingView>::Array,
338    start: usize,
339    end: usize,
340}
341
342#[cfg(feature = "views")]
343impl<'a, K, V, const SORTED: bool> MapView<'a, K, V, SORTED>
344where
345    K: super::ArrowBindingView + 'static,
346    V: super::ArrowBindingView + 'static,
347{
348    fn new(
349        keys_array: &'a <K as super::ArrowBindingView>::Array,
350        values_array: &'a <V as super::ArrowBindingView>::Array,
351        start: usize,
352        end: usize,
353    ) -> Self {
354        Self {
355            keys_array,
356            values_array,
357            start,
358            end,
359        }
360    }
361
362    /// Get the number of entries in the map.
363    #[inline]
364    pub fn len(&self) -> usize {
365        self.end - self.start
366    }
367
368    /// Check if the map is empty.
369    #[inline]
370    pub fn is_empty(&self) -> bool {
371        self.start == self.end
372    }
373}
374
375#[cfg(feature = "views")]
376impl<'a, K, V, EK, EV, const SORTED: bool> TryFrom<MapView<'a, K, V, SORTED>> for Map<K, V, SORTED>
377where
378    K: super::ArrowBindingView + 'static,
379    V: super::ArrowBindingView + 'static,
380    K::View<'a>: TryInto<K, Error = EK>,
381    V::View<'a>: TryInto<V, Error = EV>,
382    EK: Into<crate::schema::ViewAccessError>,
383    EV: Into<crate::schema::ViewAccessError>,
384{
385    type Error = crate::schema::ViewAccessError;
386
387    fn try_from(view: MapView<'a, K, V, SORTED>) -> Result<Self, Self::Error> {
388        let mut entries = Vec::with_capacity(view.len());
389        for i in view.start..view.end {
390            let key_view = K::get_view(view.keys_array, i)?;
391            let value_view = V::get_view(view.values_array, i)?;
392            entries.push((
393                key_view.try_into().map_err(|e| e.into())?,
394                value_view.try_into().map_err(|e| e.into())?,
395            ));
396        }
397        Ok(Map::new(entries))
398    }
399}
400
401#[cfg(feature = "views")]
402impl<'a, K, V, const SORTED: bool> Iterator for MapView<'a, K, V, SORTED>
403where
404    K: super::ArrowBindingView + 'static,
405    V: super::ArrowBindingView + 'static,
406{
407    type Item = Result<(K::View<'a>, V::View<'a>), crate::schema::ViewAccessError>;
408
409    fn next(&mut self) -> Option<Self::Item> {
410        if self.start < self.end {
411            let result = K::get_view(self.keys_array, self.start).and_then(|key| {
412                V::get_view(self.values_array, self.start).map(|value| (key, value))
413            });
414            self.start += 1;
415            Some(result)
416        } else {
417            None
418        }
419    }
420
421    fn size_hint(&self) -> (usize, Option<usize>) {
422        let remaining = self.end - self.start;
423        (remaining, Some(remaining))
424    }
425}
426
427#[cfg(feature = "views")]
428impl<'a, K, V, const SORTED: bool> ExactSizeIterator for MapView<'a, K, V, SORTED>
429where
430    K: super::ArrowBindingView + 'static,
431    V: super::ArrowBindingView + 'static,
432{
433    fn len(&self) -> usize {
434        self.end - self.start
435    }
436}
437
438#[cfg(feature = "views")]
439impl<K, V, const SORTED: bool> super::ArrowBindingView for Map<K, V, SORTED>
440where
441    K: ArrowBinding + super::ArrowBindingView + 'static,
442    V: ArrowBinding + super::ArrowBindingView + 'static,
443{
444    type Array = arrow_array::MapArray;
445    type View<'a> = MapView<'a, K, V, SORTED>;
446
447    fn get_view(
448        array: &Self::Array,
449        index: usize,
450    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
451        use arrow_array::Array;
452        if index >= array.len() {
453            return Err(crate::schema::ViewAccessError::OutOfBounds {
454                index,
455                len: array.len(),
456                field_name: None,
457            });
458        }
459        if array.is_null(index) {
460            return Err(crate::schema::ViewAccessError::UnexpectedNull {
461                index,
462                field_name: None,
463            });
464        }
465
466        let offsets = array.value_offsets();
467        let start = offsets[index] as usize;
468        let end = offsets[index + 1] as usize;
469
470        // MapArray entries are stored as a StructArray with "keys" and "values" fields
471        let entries = array.entries();
472        let keys_array = entries
473            .column(0)
474            .as_any()
475            .downcast_ref::<<K as super::ArrowBindingView>::Array>()
476            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
477                expected: K::data_type(),
478                actual: entries.column(0).data_type().clone(),
479                field_name: Some("keys"),
480            })?;
481        let values_array = entries
482            .column(1)
483            .as_any()
484            .downcast_ref::<<V as super::ArrowBindingView>::Array>()
485            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
486                expected: V::data_type(),
487                actual: entries.column(1).data_type().clone(),
488                field_name: Some("values"),
489            })?;
490
491        Ok(MapView::new(keys_array, values_array, start, end))
492    }
493}
494
495#[cfg(feature = "views")]
496impl<K, V> super::ArrowBindingView for OrderedMap<K, V>
497where
498    K: ArrowBinding + Ord + super::ArrowBindingView + 'static,
499    V: ArrowBinding + super::ArrowBindingView + 'static,
500{
501    type Array = arrow_array::MapArray;
502    type View<'a> = MapView<'a, K, V, true>;
503
504    fn get_view(
505        array: &Self::Array,
506        index: usize,
507    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
508        use arrow_array::Array;
509        if index >= array.len() {
510            return Err(crate::schema::ViewAccessError::OutOfBounds {
511                index,
512                len: array.len(),
513                field_name: None,
514            });
515        }
516        if array.is_null(index) {
517            return Err(crate::schema::ViewAccessError::UnexpectedNull {
518                index,
519                field_name: None,
520            });
521        }
522
523        let offsets = array.value_offsets();
524        let start = offsets[index] as usize;
525        let end = offsets[index + 1] as usize;
526
527        let entries = array.entries();
528        let keys_array = entries
529            .column(0)
530            .as_any()
531            .downcast_ref::<<K as super::ArrowBindingView>::Array>()
532            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
533                expected: K::data_type(),
534                actual: entries.column(0).data_type().clone(),
535                field_name: Some("keys"),
536            })?;
537        let values_array = entries
538            .column(1)
539            .as_any()
540            .downcast_ref::<<V as super::ArrowBindingView>::Array>()
541            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
542                expected: V::data_type(),
543                actual: entries.column(1).data_type().clone(),
544                field_name: Some("values"),
545            })?;
546
547        Ok(MapView::new(keys_array, values_array, start, end))
548    }
549}
550
551/// Iterator over views of map entries with nullable values.
552#[cfg(feature = "views")]
553pub struct MapViewNullable<'a, K, V, const SORTED: bool = false>
554where
555    K: super::ArrowBindingView + 'static,
556    V: super::ArrowBindingView + 'static,
557{
558    keys_array: &'a <K as super::ArrowBindingView>::Array,
559    values_array: &'a <V as super::ArrowBindingView>::Array,
560    start: usize,
561    end: usize,
562}
563
564#[cfg(feature = "views")]
565impl<'a, K, V, const SORTED: bool> MapViewNullable<'a, K, V, SORTED>
566where
567    K: super::ArrowBindingView + 'static,
568    V: super::ArrowBindingView + 'static,
569{
570    fn new(
571        keys_array: &'a <K as super::ArrowBindingView>::Array,
572        values_array: &'a <V as super::ArrowBindingView>::Array,
573        start: usize,
574        end: usize,
575    ) -> Self {
576        Self {
577            keys_array,
578            values_array,
579            start,
580            end,
581        }
582    }
583
584    /// Get the number of entries in the map.
585    #[inline]
586    pub fn len(&self) -> usize {
587        self.end - self.start
588    }
589
590    /// Check if the map is empty.
591    #[inline]
592    pub fn is_empty(&self) -> bool {
593        self.start == self.end
594    }
595}
596
597#[cfg(feature = "views")]
598impl<'a, K, V, EK, EV, const SORTED: bool> TryFrom<MapViewNullable<'a, K, V, SORTED>>
599    for Map<K, Option<V>, SORTED>
600where
601    K: super::ArrowBindingView + 'static,
602    V: super::ArrowBindingView + 'static,
603    K::View<'a>: TryInto<K, Error = EK>,
604    V::View<'a>: TryInto<V, Error = EV>,
605    EK: Into<crate::schema::ViewAccessError>,
606    EV: Into<crate::schema::ViewAccessError>,
607{
608    type Error = crate::schema::ViewAccessError;
609
610    fn try_from(view: MapViewNullable<'a, K, V, SORTED>) -> Result<Self, Self::Error> {
611        let mut entries = Vec::with_capacity(view.len());
612        for i in view.start..view.end {
613            use arrow_array::Array;
614            let key_view = K::get_view(view.keys_array, i)?;
615            let opt_value_view = if view.values_array.is_null(i) {
616                None
617            } else {
618                Some(V::get_view(view.values_array, i)?)
619            };
620            let opt_value_owned = match opt_value_view {
621                Some(v) => Some(v.try_into().map_err(|e| e.into())?),
622                None => None,
623            };
624            entries.push((key_view.try_into().map_err(|e| e.into())?, opt_value_owned));
625        }
626        Ok(Map::new(entries))
627    }
628}
629
630// TryFrom impls for OrderedMap (which uses MapView with SORTED=true)
631#[cfg(feature = "views")]
632impl<'a, K, V, EK, EV> TryFrom<MapView<'a, K, V, true>> for OrderedMap<K, V>
633where
634    K: super::ArrowBindingView + Ord + 'static,
635    V: super::ArrowBindingView + 'static,
636    K::View<'a>: TryInto<K, Error = EK>,
637    V::View<'a>: TryInto<V, Error = EV>,
638    EK: Into<crate::schema::ViewAccessError>,
639    EV: Into<crate::schema::ViewAccessError>,
640{
641    type Error = crate::schema::ViewAccessError;
642
643    fn try_from(view: MapView<'a, K, V, true>) -> Result<Self, Self::Error> {
644        let mut entries = std::collections::BTreeMap::new();
645        for i in view.start..view.end {
646            let key_view = K::get_view(view.keys_array, i)?;
647            let value_view = V::get_view(view.values_array, i)?;
648            entries.insert(
649                key_view.try_into().map_err(|e| e.into())?,
650                value_view.try_into().map_err(|e| e.into())?,
651            );
652        }
653        Ok(OrderedMap::new(entries))
654    }
655}
656
657#[cfg(feature = "views")]
658impl<'a, K, V, EK, EV> TryFrom<MapViewNullable<'a, K, V, true>> for OrderedMap<K, Option<V>>
659where
660    K: super::ArrowBindingView + Ord + 'static,
661    V: super::ArrowBindingView + 'static,
662    K::View<'a>: TryInto<K, Error = EK>,
663    V::View<'a>: TryInto<V, Error = EV>,
664    EK: Into<crate::schema::ViewAccessError>,
665    EV: Into<crate::schema::ViewAccessError>,
666{
667    type Error = crate::schema::ViewAccessError;
668
669    fn try_from(view: MapViewNullable<'a, K, V, true>) -> Result<Self, Self::Error> {
670        let mut entries = std::collections::BTreeMap::new();
671        for i in view.start..view.end {
672            use arrow_array::Array;
673            let key_view = K::get_view(view.keys_array, i)?;
674            let opt_value_view = if view.values_array.is_null(i) {
675                None
676            } else {
677                Some(V::get_view(view.values_array, i)?)
678            };
679            let opt_value_owned = match opt_value_view {
680                Some(v) => Some(v.try_into().map_err(|e| e.into())?),
681                None => None,
682            };
683            entries.insert(key_view.try_into().map_err(|e| e.into())?, opt_value_owned);
684        }
685        Ok(OrderedMap::new(entries))
686    }
687}
688
689#[cfg(feature = "views")]
690impl<'a, K, V, const SORTED: bool> Iterator for MapViewNullable<'a, K, V, SORTED>
691where
692    K: super::ArrowBindingView + 'static,
693    V: super::ArrowBindingView + 'static,
694{
695    type Item = Result<(K::View<'a>, Option<V::View<'a>>), crate::schema::ViewAccessError>;
696
697    fn next(&mut self) -> Option<Self::Item> {
698        if self.start < self.end {
699            let result = K::get_view(self.keys_array, self.start).and_then(|key| {
700                use arrow_array::Array;
701                let value = if self.values_array.is_null(self.start) {
702                    Ok(None)
703                } else {
704                    V::get_view(self.values_array, self.start).map(Some)
705                };
706                value.map(|v| (key, v))
707            });
708            self.start += 1;
709            Some(result)
710        } else {
711            None
712        }
713    }
714
715    fn size_hint(&self) -> (usize, Option<usize>) {
716        let remaining = self.end - self.start;
717        (remaining, Some(remaining))
718    }
719}
720
721#[cfg(feature = "views")]
722impl<'a, K, V, const SORTED: bool> ExactSizeIterator for MapViewNullable<'a, K, V, SORTED>
723where
724    K: super::ArrowBindingView + 'static,
725    V: super::ArrowBindingView + 'static,
726{
727    fn len(&self) -> usize {
728        self.end - self.start
729    }
730}
731
732#[cfg(feature = "views")]
733impl<K, V, const SORTED: bool> super::ArrowBindingView for Map<K, Option<V>, SORTED>
734where
735    K: ArrowBinding + super::ArrowBindingView + 'static,
736    V: ArrowBinding + super::ArrowBindingView + 'static,
737{
738    type Array = arrow_array::MapArray;
739    type View<'a> = MapViewNullable<'a, K, V, SORTED>;
740
741    fn get_view(
742        array: &Self::Array,
743        index: usize,
744    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
745        use arrow_array::Array;
746        if index >= array.len() {
747            return Err(crate::schema::ViewAccessError::OutOfBounds {
748                index,
749                len: array.len(),
750                field_name: None,
751            });
752        }
753        if array.is_null(index) {
754            return Err(crate::schema::ViewAccessError::UnexpectedNull {
755                index,
756                field_name: None,
757            });
758        }
759
760        let offsets = array.value_offsets();
761        let start = offsets[index] as usize;
762        let end = offsets[index + 1] as usize;
763
764        let entries = array.entries();
765        let keys_array = entries
766            .column(0)
767            .as_any()
768            .downcast_ref::<<K as super::ArrowBindingView>::Array>()
769            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
770                expected: K::data_type(),
771                actual: entries.column(0).data_type().clone(),
772                field_name: Some("keys"),
773            })?;
774        let values_array = entries
775            .column(1)
776            .as_any()
777            .downcast_ref::<<V as super::ArrowBindingView>::Array>()
778            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
779                expected: V::data_type(),
780                actual: entries.column(1).data_type().clone(),
781                field_name: Some("values"),
782            })?;
783
784        Ok(MapViewNullable::new(keys_array, values_array, start, end))
785    }
786}
787
788#[cfg(feature = "views")]
789impl<K, V> super::ArrowBindingView for OrderedMap<K, Option<V>>
790where
791    K: ArrowBinding + Ord + super::ArrowBindingView + 'static,
792    V: ArrowBinding + super::ArrowBindingView + 'static,
793{
794    type Array = arrow_array::MapArray;
795    type View<'a> = MapViewNullable<'a, K, V, true>;
796
797    fn get_view(
798        array: &Self::Array,
799        index: usize,
800    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
801        use arrow_array::Array;
802        if index >= array.len() {
803            return Err(crate::schema::ViewAccessError::OutOfBounds {
804                index,
805                len: array.len(),
806                field_name: None,
807            });
808        }
809        if array.is_null(index) {
810            return Err(crate::schema::ViewAccessError::UnexpectedNull {
811                index,
812                field_name: None,
813            });
814        }
815
816        let offsets = array.value_offsets();
817        let start = offsets[index] as usize;
818        let end = offsets[index + 1] as usize;
819
820        let entries = array.entries();
821        let keys_array = entries
822            .column(0)
823            .as_any()
824            .downcast_ref::<<K as super::ArrowBindingView>::Array>()
825            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
826                expected: K::data_type(),
827                actual: entries.column(0).data_type().clone(),
828                field_name: Some("keys"),
829            })?;
830        let values_array = entries
831            .column(1)
832            .as_any()
833            .downcast_ref::<<V as super::ArrowBindingView>::Array>()
834            .ok_or_else(|| crate::schema::ViewAccessError::TypeMismatch {
835                expected: V::data_type(),
836                actual: entries.column(1).data_type().clone(),
837                field_name: Some("values"),
838            })?;
839
840        Ok(MapViewNullable::new(keys_array, values_array, start, end))
841    }
842}