use crate::builder::{ArrayBuilder, GenericBinaryBuilder};
use crate::{Array, ArrayRef, GenericStringArray, OffsetSizeTrait};
use std::any::Any;
use std::sync::Arc;
#[derive(Debug)]
pub struct GenericStringBuilder<OffsetSize: OffsetSizeTrait> {
builder: GenericBinaryBuilder<OffsetSize>,
}
impl<OffsetSize: OffsetSizeTrait> GenericStringBuilder<OffsetSize> {
pub fn new() -> Self {
Self {
builder: GenericBinaryBuilder::new(),
}
}
pub fn with_capacity(item_capacity: usize, data_capacity: usize) -> Self {
Self {
builder: GenericBinaryBuilder::with_capacity(item_capacity, data_capacity),
}
}
#[inline]
pub fn append_value(&mut self, value: impl AsRef<str>) {
self.builder.append_value(value.as_ref().as_bytes());
}
#[inline]
pub fn append_null(&mut self) {
self.builder.append_null()
}
#[inline]
pub fn append_option(&mut self, value: Option<impl AsRef<str>>) {
match value {
None => self.append_null(),
Some(v) => self.append_value(v),
};
}
pub fn finish(&mut self) -> GenericStringArray<OffsetSize> {
let t = GenericStringArray::<OffsetSize>::DATA_TYPE;
let v = self.builder.finish();
let builder = v.into_data().into_builder().data_type(t);
let data = unsafe { builder.build_unchecked() };
data.into()
}
pub fn values_slice(&self) -> &[u8] {
self.builder.values_slice()
}
pub fn offsets_slice(&self) -> &[OffsetSize] {
self.builder.offsets_slice()
}
}
impl<OffsetSize: OffsetSizeTrait> Default for GenericStringBuilder<OffsetSize> {
fn default() -> Self {
Self::new()
}
}
impl<OffsetSize: OffsetSizeTrait> ArrayBuilder for GenericStringBuilder<OffsetSize> {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn len(&self) -> usize {
self.builder.len()
}
fn is_empty(&self) -> bool {
self.builder.is_empty()
}
fn finish(&mut self) -> ArrayRef {
let a = GenericStringBuilder::<OffsetSize>::finish(self);
Arc::new(a)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::array::{Array, OffsetSizeTrait};
use crate::builder::ArrayBuilder;
fn _test_generic_string_array_builder<O: OffsetSizeTrait>() {
let mut builder = GenericStringBuilder::<O>::new();
let owned = "arrow".to_owned();
builder.append_value("hello");
builder.append_value("");
builder.append_value(&owned);
builder.append_null();
builder.append_option(Some("rust"));
builder.append_option(None::<&str>);
builder.append_option(None::<String>);
assert_eq!(7, builder.len());
assert_eq!(
GenericStringArray::<O>::from(vec![
Some("hello"),
Some(""),
Some("arrow"),
None,
Some("rust"),
None,
None
]),
builder.finish()
);
}
#[test]
fn test_string_array_builder() {
_test_generic_string_array_builder::<i32>()
}
#[test]
fn test_large_string_array_builder() {
_test_generic_string_array_builder::<i64>()
}
fn _test_generic_string_array_builder_finish<O: OffsetSizeTrait>() {
let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
builder.append_value("hello");
builder.append_value("rust");
builder.append_null();
builder.finish();
assert!(builder.is_empty());
assert_eq!(&[O::zero()], builder.offsets_slice());
builder.append_value("arrow");
builder.append_value("parquet");
let arr = builder.finish();
assert_eq!(None, arr.data().null_buffer());
assert_eq!(GenericStringArray::<O>::from(vec!["arrow", "parquet"]), arr,)
}
#[test]
fn test_string_array_builder_finish() {
_test_generic_string_array_builder_finish::<i32>()
}
#[test]
fn test_large_string_array_builder_finish() {
_test_generic_string_array_builder_finish::<i64>()
}
}