use crate::array::{
ArrayBuilder, ArrayRef, GenericListBuilder, GenericStringArray, OffsetSizeTrait,
UInt8Builder,
};
use std::any::Any;
use std::sync::Arc;
#[derive(Debug)]
pub struct GenericStringBuilder<OffsetSize: OffsetSizeTrait> {
builder: GenericListBuilder<OffsetSize, UInt8Builder>,
}
impl<OffsetSize: OffsetSizeTrait> GenericStringBuilder<OffsetSize> {
pub fn new(capacity: usize) -> Self {
let values_builder = UInt8Builder::new(capacity);
Self {
builder: GenericListBuilder::new(values_builder),
}
}
pub fn with_capacity(item_capacity: usize, data_capacity: usize) -> Self {
let values_builder = UInt8Builder::new(data_capacity);
Self {
builder: GenericListBuilder::with_capacity(values_builder, item_capacity),
}
}
#[inline]
pub fn append_value(&mut self, value: impl AsRef<str>) {
self.builder
.values()
.append_slice(value.as_ref().as_bytes());
self.builder.append(true);
}
#[inline]
pub fn append(&mut self, is_valid: bool) {
self.builder.append(is_valid)
}
#[inline]
pub fn append_null(&mut self) {
self.append(false)
}
#[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> {
GenericStringArray::<OffsetSize>::from(self.builder.finish())
}
pub fn values_slice(&self) -> &[u8] {
self.builder.values_ref().values_slice()
}
pub fn offsets_slice(&self) -> &[OffsetSize] {
self.builder.offsets_slice()
}
}
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 crate::array::builder::StringBuilder;
use crate::array::{Array, ArrayBuilder};
#[test]
fn test_string_array_builder() {
let mut builder = StringBuilder::new(20);
builder.append_value("hello");
builder.append(true);
builder.append_value("world");
let string_array = builder.finish();
assert_eq!(3, string_array.len());
assert_eq!(0, string_array.null_count());
assert_eq!("hello", string_array.value(0));
assert_eq!("", string_array.value(1));
assert_eq!("world", string_array.value(2));
assert_eq!(5, string_array.value_offsets()[2]);
assert_eq!(5, string_array.value_length(2));
}
#[test]
fn test_string_array_builder_finish() {
let mut builder = StringBuilder::new(10);
builder.append_value("hello");
builder.append_value("world");
let mut arr = builder.finish();
assert_eq!(2, arr.len());
assert_eq!(0, builder.len());
builder.append_value("arrow");
arr = builder.finish();
assert_eq!(1, arr.len());
assert_eq!(0, builder.len());
}
#[test]
fn test_string_array_builder_append_string() {
let mut builder = StringBuilder::new(20);
let var = "hello".to_owned();
builder.append_value(&var);
builder.append(true);
builder.append_value("world");
let string_array = builder.finish();
assert_eq!(3, string_array.len());
assert_eq!(0, string_array.null_count());
assert_eq!("hello", string_array.value(0));
assert_eq!("", string_array.value(1));
assert_eq!("world", string_array.value(2));
assert_eq!(5, string_array.value_offsets()[2]);
assert_eq!(5, string_array.value_length(2));
}
#[test]
fn test_string_array_builder_append_option() {
let mut builder = StringBuilder::new(20);
builder.append_option(Some("hello"));
builder.append_option(None::<&str>);
builder.append_option(None::<String>);
builder.append_option(Some("world"));
let string_array = builder.finish();
assert_eq!(4, string_array.len());
assert_eq!("hello", string_array.value(0));
assert!(string_array.is_null(1));
assert!(string_array.is_null(2));
assert_eq!("world", string_array.value(3));
}
}