use std::io::Write;
use arrow::array::*;
use arrow::chunk::Chunk;
use arrow::error::Result;
use arrow::io::parquet::write::{
num_values, slice_parquet_array, to_leaves, to_nested, to_parquet_leaves, SchemaDescriptor,
};
use crate::compression::CommonCompression;
use crate::compression::Compression;
use crate::ColumnMeta;
use crate::PageMeta;
use crate::CONTINUATION_MARKER;
use super::{write, NativeWriter};
#[derive(Debug, Clone, PartialEq, Default)]
pub struct WriteOptions {
pub default_compression: CommonCompression,
pub default_compress_ratio: Option<f64>,
pub max_page_size: Option<usize>,
pub forbidden_compressions: Vec<Compression>,
}
impl<W: Write> NativeWriter<W> {
pub fn encode_chunk(
&mut self,
schema_descriptor: SchemaDescriptor,
chunk: &Chunk<Box<dyn Array>>,
) -> Result<()> {
let page_size = self
.options
.max_page_size
.unwrap_or(chunk.len())
.min(chunk.len());
for (array, type_) in chunk
.arrays()
.iter()
.zip(schema_descriptor.fields().to_vec())
{
let array = array.as_ref();
let nested = to_nested(array, &type_)?;
let types: Vec<parquet2::schema::types::PrimitiveType> = to_parquet_leaves(type_);
let leaf_arrays = to_leaves(array);
let length = array.len();
for ((leaf_array, nested), type_) in leaf_arrays
.iter()
.zip(nested.into_iter())
.zip(types.into_iter())
{
let start = self.writer.offset;
let leaf_array = leaf_array.to_boxed();
let page_metas: Vec<PageMeta> = (0..length)
.step_by(page_size)
.map(|offset| {
let length = if offset + page_size > length {
length - offset
} else {
page_size
};
let mut sub_array = leaf_array.clone();
let mut sub_nested = nested.clone();
slice_parquet_array(sub_array.as_mut(), &mut sub_nested, offset, length);
let page_start = self.writer.offset;
write(
&mut self.writer,
sub_array.as_ref(),
&sub_nested,
type_.clone(),
length,
self.options.clone(),
&mut self.scratch,
)
.unwrap();
let page_end = self.writer.offset;
let num_values = num_values(&sub_nested);
PageMeta {
length: (page_end - page_start),
num_values: num_values as u64,
}
})
.collect();
self.metas.push(ColumnMeta {
offset: start,
pages: page_metas,
})
}
}
Ok(())
}
}
pub fn write_continuation<W: Write>(writer: &mut W, total_len: i32) -> Result<usize> {
writer.write_all(&CONTINUATION_MARKER)?;
writer.write_all(&total_len.to_le_bytes()[..])?;
Ok(8)
}