serde_arrow 0.14.0

Convert sequences of Rust objects to Arrow arrays and back again
Documentation
use std::collections::{BTreeMap, HashMap};

use marrow::{
    array::{Array, MapArray},
    datatypes::{FieldMeta, MapMeta},
};
use serde::{Serialize, Serializer};

use crate::internal::{
    error::{prepend, set_default, Context, ContextSupport, Error, Result},
    serialization::utils::impl_serializer,
    utils::array_ext::{ArrayExt, OffsetsArray, SeqArrayExt},
};

use super::array_builder::ArrayBuilder;

#[derive(Debug, Clone)]
pub struct MapBuilder {
    pub name: String,
    entries_name: String,
    sorted: bool,
    pub keys: Box<ArrayBuilder>,
    pub values: Box<ArrayBuilder>,
    pub offsets: OffsetsArray<i32>,
    pub metadata: HashMap<String, String>,
}

impl MapBuilder {
    pub fn new(
        name: String,
        entries_name: String,
        sorted: bool,
        keys: ArrayBuilder,
        values: ArrayBuilder,
        is_nullable: bool,
        metadata: HashMap<String, String>,
    ) -> Result<Self> {
        Ok(Self {
            name,
            entries_name,
            sorted,
            offsets: OffsetsArray::new(is_nullable),
            keys: Box::new(keys),
            values: Box::new(values),
            metadata,
        })
    }

    pub fn take(&mut self) -> ArrayBuilder {
        ArrayBuilder::Map(Self {
            name: self.name.clone(),
            entries_name: self.entries_name.clone(),
            sorted: self.sorted,
            metadata: self.metadata.clone(),
            offsets: self.offsets.take(),
            keys: Box::new(self.keys.take()),
            values: Box::new(self.values.take()),
        })
    }

    pub fn is_nullable(&self) -> bool {
        self.offsets.validity.is_some()
    }

    pub fn into_array_and_field_meta(self) -> Result<(Array, FieldMeta)> {
        let meta = FieldMeta {
            name: self.name,
            nullable: self.offsets.is_nullable(),
            metadata: self.metadata,
        };
        let (keys, keys_meta) = (*self.keys).into_array_and_field_meta()?;
        let (values, values_meta) = (*self.values).into_array_and_field_meta()?;

        let array = Array::Map(MapArray {
            meta: MapMeta {
                entries_name: self.entries_name,
                sorted: self.sorted,
                keys: keys_meta,
                values: values_meta,
            },
            keys: Box::new(keys),
            values: Box::new(values),
            validity: self.offsets.validity,
            offsets: self.offsets.offsets,
        });
        Ok((array, meta))
    }

    pub fn reserve(&mut self, additional: usize) {
        self.offsets.reserve(additional);
    }

    pub fn serialize_default_value(&mut self) -> Result<()> {
        self.offsets.push_seq_default().ctx(self)
    }

    pub fn serialize_value<V: Serialize>(&mut self, value: V) -> Result<()> {
        value.serialize(&mut *self).ctx(self)
    }
}

impl Context for MapBuilder {
    fn annotate(&self, annotations: &mut BTreeMap<String, String>) {
        prepend(annotations, "field", &self.name);
        set_default(annotations, "data_type", "Map");
    }
}

impl<'a> Serializer for &'a mut MapBuilder {
    impl_serializer!(
        'a, MapBuilder;
        override serialize_none,
        override serialize_map,
    );

    fn serialize_none(self) -> Result<()> {
        self.offsets.push_seq_none()
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
        if let Some(len) = len {
            self.keys.reserve(len);
            self.values.reserve(len);
        }
        self.offsets.start_seq().ctx(self)?;
        Ok(Self::SerializeMap::Map(self))
    }
}

impl serde::ser::SerializeMap for &mut MapBuilder {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
        self.offsets.push_seq_elements(1)?;
        self.keys.serialize_value(key)
    }

    fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
        self.values.serialize_value(value)
    }

    fn end(self) -> Result<()> {
        self.offsets.end_seq()
    }
}