serde_arrow 0.14.0

Convert sequences of Rust objects to Arrow arrays and back again
Documentation
use marrow::view::FixedSizeBinaryView;
use serde::de::Visitor;

use crate::internal::error::{
    fail, set_default, try_, Context, ContextSupport, Error, ErrorKind, Result,
};

use super::{
    random_access_deserializer::RandomAccessDeserializer,
    utils::{bitset_is_set, U8SliceDeserializer},
};

pub struct FixedSizeBinaryDeserializer<'a> {
    pub path: String,
    pub view: FixedSizeBinaryView<'a>,
    pub len: usize,
    pub n: usize,
}

impl<'a> FixedSizeBinaryDeserializer<'a> {
    pub fn new(path: String, view: FixedSizeBinaryView<'a>) -> Result<Self> {
        let n = usize::try_from(view.n)?;
        if view.data.len() % n != 0 {
            fail!(
                concat!(
                    "Invalid FixedSizeBinary array: Data of len {len} is not ",
                    "evenly divisible into chunks of size {n}",
                ),
                len = view.data.len(),
                n = n,
            );
        }

        Ok(Self {
            path,
            len: view.data.len() / n,
            view,
            n,
        })
    }

    pub fn get(&self, idx: usize) -> Result<Option<&'a [u8]>> {
        if idx >= self.len {
            fail!("Out of bounds access")
        }
        if let Some(validity) = &self.view.validity {
            if !bitset_is_set(validity, idx)? {
                return Ok(None);
            }
        }
        let start = idx * self.n;
        let end = (idx + 1) * self.n;
        Ok(Some(&self.view.data[start..end]))
    }

    pub fn get_required(&self, idx: usize) -> Result<&'a [u8]> {
        let Some(s) = self.get(idx)? else {
            return Err(Error::new(
                ErrorKind::NullabilityViolation { field: None },
                "Required value is not defined".into(),
            ));
        };
        Ok(s)
    }
}

impl Context for FixedSizeBinaryDeserializer<'_> {
    fn annotate(&self, annotations: &mut std::collections::BTreeMap<String, String>) {
        set_default(annotations, "field", &self.path);
        set_default(
            annotations,
            "data_type",
            format!("FixedSizeBinary({n})", n = self.n),
        );
    }
}

impl<'de> RandomAccessDeserializer<'de> for FixedSizeBinaryDeserializer<'de> {
    fn is_some(&self, idx: usize) -> Result<bool> {
        Ok(self.get(idx)?.is_some())
    }

    fn deserialize_any_some<V: Visitor<'de>>(&self, visitor: V, idx: usize) -> Result<V::Value> {
        self.deserialize_bytes(visitor, idx)
    }

    fn deserialize_bytes<V: Visitor<'de>>(&self, visitor: V, idx: usize) -> Result<V::Value> {
        try_(|| visitor.visit_borrowed_bytes(self.get_required(idx)?)).ctx(self)
    }

    fn deserialize_byte_buf<V: Visitor<'de>>(&self, visitor: V, idx: usize) -> Result<V::Value> {
        try_(|| visitor.visit_borrowed_bytes(self.get_required(idx)?)).ctx(self)
    }

    fn deserialize_seq<V: Visitor<'de>>(&self, visitor: V, idx: usize) -> Result<V::Value> {
        try_(|| visitor.visit_seq(U8SliceDeserializer::new(self.get_required(idx)?))).ctx(self)
    }
}