From 52655f3629b6ecc85b63f906bc513b915618d21b Mon Sep 17 00:00:00 2001 From: shekharrajak Date: Fri, 15 May 2026 22:47:54 +0530 Subject: [PATCH 1/2] feat: add VariantArrayBuilder::build_shredded --- .../src/variant_array_builder.rs | 233 +++++++++++++++++- 1 file changed, 225 insertions(+), 8 deletions(-) diff --git a/parquet-variant-compute/src/variant_array_builder.rs b/parquet-variant-compute/src/variant_array_builder.rs index e669277f1d06..f970177d31f6 100644 --- a/parquet-variant-compute/src/variant_array_builder.rs +++ b/parquet-variant-compute/src/variant_array_builder.rs @@ -17,7 +17,7 @@ //! [`VariantArrayBuilder`] implementation -use crate::VariantArray; +use crate::{VariantArray, shred_variant}; use arrow::array::{ArrayRef, BinaryViewArray, BinaryViewBuilder, NullBufferBuilder, StructArray}; use arrow_schema::{ArrowError, DataType, Field, Fields}; use parquet_variant::{ @@ -37,9 +37,6 @@ use std::sync::Arc; /// This builder always creates a `VariantArray` using [`BinaryViewArray`] for both /// the metadata and value fields. /// -/// # TODO -/// 1. Support shredding: -/// /// ## Example: /// ``` /// # use arrow::array::Array; @@ -82,6 +79,34 @@ use std::sync::Arc; /// let value = variant_array.value(4); /// assert_eq!(value, Variant::ShortString(ShortString::try_new("norm").unwrap())); /// ``` +/// +/// ## Shredded Example +/// +/// Use [`Self::build_shredded`] with [`ShreddedSchemaBuilder`] to produce a +/// shredded [`VariantArray`] where known fields are extracted into typed columns. +/// +/// ``` +/// # use arrow::array::Array; +/// # use arrow_schema::DataType; +/// # use parquet_variant::{Variant, VariantBuilderExt}; +/// # use parquet_variant_compute::{ShreddedSchemaBuilder, VariantArrayBuilder}; +/// let schema = ShreddedSchemaBuilder::default() +/// .with_path("brand", &DataType::Utf8).unwrap() +/// .with_path("price", &DataType::Float64).unwrap() +/// .build(); +/// +/// let mut builder = VariantArrayBuilder::new(3); +/// builder.new_object().with_field("brand", "Apple").with_field("price", 999.0f64).finish(); +/// builder.new_object().with_field("brand", "Samsung").finish(); +/// builder.append_null(); +/// +/// let arr = builder.build_shredded(&schema).unwrap(); +/// assert_eq!(arr.len(), 3); +/// assert!(arr.typed_value_field().is_some()); +/// assert!(!arr.is_null(0)); +/// assert!(!arr.is_null(1)); +/// assert!(arr.is_null(2)); +/// ``` #[derive(Debug)] pub struct VariantArrayBuilder { /// Nulls @@ -96,8 +121,7 @@ pub struct VariantArrayBuilder { value_offsets: Vec, /// The fields of the final `StructArray` /// - /// TODO: 1) Add extension type metadata - /// TODO: 2) Add support for shredding + /// TODO: Add extension type metadata fields: Fields, } @@ -117,7 +141,7 @@ impl VariantArrayBuilder { } } - /// Build the final builder + /// Build the final [`VariantArray`] (unshredded). pub fn build(self) -> VariantArray { let Self { mut nulls, @@ -134,7 +158,6 @@ impl VariantArrayBuilder { let value_buffer = value_builder.into_inner(); let value_array = binary_view_array_from_buffers(value_buffer, value_offsets); - // The build the final struct array let inner = StructArray::new( fields, vec![ @@ -148,6 +171,13 @@ impl VariantArrayBuilder { VariantArray::try_new(&inner).expect("valid VariantArray by construction") } + /// Build a shredded [`VariantArray`] using `as_type` as the shredding schema. + /// Use [`ShreddedSchemaBuilder`] to construct `as_type` for struct schemas. + /// Returns `Err` if `as_type` is not a valid variant shredding type. + pub fn build_shredded(self, as_type: &DataType) -> Result { + shred_variant(&self.build(), as_type) + } + /// Appends a null row to the builder. pub fn append_null(&mut self) { self.nulls.append_null(); @@ -471,6 +501,7 @@ fn binary_view_array_from_buffers(buffer: Vec, offsets: Vec) -> Binar #[cfg(test)] mod test { use super::*; + use crate::ShreddedSchemaBuilder; use arrow::array::Array; use parquet_variant::{ShortString, Variant}; @@ -659,4 +690,190 @@ mod test { assert_eq!(array.value(2), array2.value(2).get_list_element(0).unwrap()); assert_eq!(array.value(2), array2.value(2).get_list_element(1).unwrap()); } + + #[test] + fn build_shredded_primitive_int64() { + let mut b = VariantArrayBuilder::new(3); + b.append_variant(Variant::Int64(42)); + b.append_variant(Variant::Int64(100)); + b.append_null(); + let arr = b.build_shredded(&DataType::Int64).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 3); + assert!(!arr.is_null(0)); + assert!(!arr.is_null(1)); + assert!(arr.is_null(2)); + } + + #[test] + fn build_shredded_primitive_utf8() { + let mut b = VariantArrayBuilder::new(2); + b.append_variant(Variant::from("hello")); + b.append_null(); + let arr = b.build_shredded(&DataType::Utf8).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + assert!(!arr.is_null(0)); + assert!(arr.is_null(1)); + } + + #[test] + fn build_shredded_primitive_float64() { + let mut b = VariantArrayBuilder::new(2); + b.append_variant(Variant::Float(3.14)); + b.append_null(); + let arr = b.build_shredded(&DataType::Float64).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + } + + #[test] + fn build_shredded_primitive_bool() { + let mut b = VariantArrayBuilder::new(2); + b.append_variant(Variant::BooleanTrue); + b.append_variant(Variant::BooleanFalse); + let arr = b.build_shredded(&DataType::Boolean).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + } + + #[test] + fn build_shredded_type_mismatch_falls_back_to_value_column() { + // Row 0: matches Int64 -> typed_value non-null, value null + // Row 1: string, does not match -> value non-null, typed_value null + let mut b = VariantArrayBuilder::new(2); + b.append_variant(Variant::Int64(7)); + b.append_variant(Variant::from("not an int")); + let arr = b.build_shredded(&DataType::Int64).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + assert!(!arr.is_null(0)); + assert!(!arr.is_null(1)); + } + + #[test] + fn build_shredded_struct_single_field() { + let schema = DataType::Struct(vec![Field::new("brand", DataType::Utf8, true)].into()); + let mut b = VariantArrayBuilder::new(3); + b.new_object().with_field("brand", "Apple").finish(); + b.new_object().with_field("brand", "Samsung").finish(); + b.append_null(); + let arr = b.build_shredded(&schema).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 3); + assert!(!arr.is_null(0)); + assert!(!arr.is_null(1)); + assert!(arr.is_null(2)); + } + + #[test] + fn build_shredded_struct_multi_field() { + let schema = ShreddedSchemaBuilder::default() + .with_path("name", &DataType::Utf8) + .unwrap() + .with_path("age", &DataType::Int32) + .unwrap() + .build(); + let mut b = VariantArrayBuilder::new(2); + b.new_object() + .with_field("name", "Alice") + .with_field("age", 30i32) + .finish(); + b.new_object().with_field("name", "Bob").finish(); + let arr = b.build_shredded(&schema).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + } + + #[test] + fn build_shredded_nested_struct() { + let schema = ShreddedSchemaBuilder::default() + .with_path("address.city", &DataType::Utf8) + .unwrap() + .with_path("address.zip", &DataType::Utf8) + .unwrap() + .build(); + let mut b = VariantArrayBuilder::new(2); + { + let mut obj = b.new_object(); + obj.new_object("address") + .with_field("city", "NYC") + .with_field("zip", "10001") + .finish(); + obj.finish(); + } + b.append_null(); + let arr = b.build_shredded(&schema).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + assert!(!arr.is_null(0)); + assert!(arr.is_null(1)); + } + + #[test] + fn build_shredded_list_of_int64() { + use arrow_schema::Field as ArrowField; + use std::sync::Arc; + let list_schema = DataType::List(Arc::new(ArrowField::new("item", DataType::Int64, true))); + let mut b = VariantArrayBuilder::new(2); + b.new_list() + .with_value(Variant::Int64(1)) + .with_value(Variant::Int64(2)) + .finish(); + b.append_null(); + let arr = b.build_shredded(&list_schema).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 2); + assert!(!arr.is_null(0)); + assert!(arr.is_null(1)); + } + + #[test] + fn build_shredded_extend_then_shred() { + let mut b = VariantArrayBuilder::new(4); + b.extend([ + Some(Variant::Int64(1)), + None, + Some(Variant::Int64(3)), + Some(Variant::from("oops")), + ]); + let arr = b.build_shredded(&DataType::Int64).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 4); + assert!(!arr.is_null(0)); + assert!(arr.is_null(1)); + assert!(!arr.is_null(2)); + assert!(!arr.is_null(3)); + } + + #[test] + fn build_shredded_all_nulls() { + let mut b = VariantArrayBuilder::new(3); + b.append_null(); + b.append_null(); + b.append_null(); + let arr = b.build_shredded(&DataType::Int64).unwrap(); + assert_eq!(arr.len(), 3); + assert!(arr.is_null(0)); + assert!(arr.is_null(1)); + assert!(arr.is_null(2)); + } + + #[test] + fn build_shredded_invalid_type_returns_err() { + let mut b = VariantArrayBuilder::new(1); + b.append_variant(Variant::Int64(1)); + let result = b.build_shredded(&DataType::FixedSizeBinary(17)); + assert!(result.is_err()); + } + + #[test] + fn build_shredded_uuid_fixed_size_binary_16() { + let uuid_bytes: Vec = (0u8..16).collect(); + let mut b = VariantArrayBuilder::new(1); + b.append_variant(Variant::from(uuid_bytes.as_slice())); + let arr = b.build_shredded(&DataType::FixedSizeBinary(16)).unwrap(); + assert!(arr.typed_value_field().is_some()); + assert_eq!(arr.len(), 1); + } } From b9bf55741bc5b333667c0f95d06fb6b52d8d6574 Mon Sep 17 00:00:00 2001 From: shekharrajak Date: Thu, 4 Jun 2026 22:32:51 +0530 Subject: [PATCH 2/2] Add shredded variant builder --- parquet-variant-compute/src/lib.rs | 4 +- .../src/variant_array_builder.rs | 238 +++++++++++++++++- 2 files changed, 230 insertions(+), 12 deletions(-) diff --git a/parquet-variant-compute/src/lib.rs b/parquet-variant-compute/src/lib.rs index 066fe15b7c8b..f28e0cd2d26f 100644 --- a/parquet-variant-compute/src/lib.rs +++ b/parquet-variant-compute/src/lib.rs @@ -52,7 +52,9 @@ mod variant_get; mod variant_to_arrow; pub use variant_array::{ShreddingState, VariantArray, VariantType}; -pub use variant_array_builder::{VariantArrayBuilder, VariantValueArrayBuilder}; +pub use variant_array_builder::{ + ShreddedVariantArrayBuilder, VariantArrayBuilder, VariantValueArrayBuilder, +}; pub use cast_to_variant::{cast_to_variant, cast_to_variant_with_options}; pub use from_json::json_to_variant; diff --git a/parquet-variant-compute/src/variant_array_builder.rs b/parquet-variant-compute/src/variant_array_builder.rs index f970177d31f6..144df7bc24b2 100644 --- a/parquet-variant-compute/src/variant_array_builder.rs +++ b/parquet-variant-compute/src/variant_array_builder.rs @@ -82,8 +82,9 @@ use std::sync::Arc; /// /// ## Shredded Example /// -/// Use [`Self::build_shredded`] with [`ShreddedSchemaBuilder`] to produce a -/// shredded [`VariantArray`] where known fields are extracted into typed columns. +/// Use [`Self::build_shredded`] or [`Self::with_shredding_schema`] with +/// [`ShreddedSchemaBuilder`] to produce a shredded [`VariantArray`] where known +/// fields are extracted into typed columns. /// /// ``` /// # use arrow::array::Array; @@ -95,12 +96,12 @@ use std::sync::Arc; /// .with_path("price", &DataType::Float64).unwrap() /// .build(); /// -/// let mut builder = VariantArrayBuilder::new(3); +/// let mut builder = VariantArrayBuilder::new(3).with_shredding_schema(schema); /// builder.new_object().with_field("brand", "Apple").with_field("price", 999.0f64).finish(); /// builder.new_object().with_field("brand", "Samsung").finish(); /// builder.append_null(); /// -/// let arr = builder.build_shredded(&schema).unwrap(); +/// let arr = builder.try_build().unwrap(); /// assert_eq!(arr.len(), 3); /// assert!(arr.typed_value_field().is_some()); /// assert!(!arr.is_null(0)); @@ -178,6 +179,15 @@ impl VariantArrayBuilder { shred_variant(&self.build(), as_type) } + /// Configure this builder to produce a shredded [`VariantArray`]. + /// + /// The returned builder keeps [`Self::build`] infallible for unshredded + /// arrays, and exposes [`ShreddedVariantArrayBuilder::try_build`] for the + /// fallible shredded path. + pub fn with_shredding_schema(self, as_type: DataType) -> ShreddedVariantArrayBuilder { + ShreddedVariantArrayBuilder::new(self, as_type) + } + /// Appends a null row to the builder. pub fn append_null(&mut self) { self.nulls.append_null(); @@ -215,6 +225,47 @@ impl VariantArrayBuilder { } } +/// A [`VariantArrayBuilder`] configured to build a shredded [`VariantArray`]. +/// +/// This type preserves the chain-style configuration API while keeping +/// [`VariantArrayBuilder::build`] infallible for unshredded arrays. +#[derive(Debug)] +pub struct ShreddedVariantArrayBuilder { + builder: VariantArrayBuilder, + as_type: DataType, +} + +impl ShreddedVariantArrayBuilder { + /// Create a shredded builder from an existing [`VariantArrayBuilder`] and + /// shredding schema. + pub fn new(builder: VariantArrayBuilder, as_type: DataType) -> Self { + Self { builder, as_type } + } + + /// Build the final shredded [`VariantArray`]. + /// + /// Returns `Err` if the configured shredding schema is not a valid variant + /// shredding type. + pub fn try_build(self) -> Result { + self.builder.build_shredded(&self.as_type) + } + + /// Appends a null row to the builder. + pub fn append_null(&mut self) { + self.builder.append_null(); + } + + /// Appends `n` null rows to the builder. + pub fn append_nulls(&mut self, n: usize) { + self.builder.append_nulls(n); + } + + /// Append the [`Variant`] to the builder as the next row. + pub fn append_variant(&mut self, variant: Variant) { + self.builder.append_variant(variant); + } +} + impl<'m, 'v> Extend>> for VariantArrayBuilder { fn extend>>>(&mut self, iter: T) { for v in iter { @@ -226,6 +277,12 @@ impl<'m, 'v> Extend>> for VariantArrayBuilder { } } +impl<'m, 'v> Extend>> for ShreddedVariantArrayBuilder { + fn extend>>>(&mut self, iter: T) { + self.builder.extend(iter); + } +} + /// Builder-specific state for array building that manages array-level offsets and nulls. See /// [`VariantBuilderExt`] for details. #[derive(Debug)] @@ -272,6 +329,30 @@ impl VariantBuilderExt for VariantArrayBuilder { } } +impl VariantBuilderExt for ShreddedVariantArrayBuilder { + type State<'a> + = ArrayBuilderState<'a> + where + Self: 'a; + + /// Appending NULL to a variant array produces an actual NULL value + fn append_null(&mut self) { + self.append_null(); + } + + fn append_value<'m, 'v>(&mut self, value: impl Into>) { + self.append_variant(value.into()); + } + + fn try_new_list(&mut self) -> Result>, ArrowError> { + Ok(ListBuilder::new(self.builder.parent_state(), false)) + } + + fn try_new_object(&mut self) -> Result>, ArrowError> { + Ok(ObjectBuilder::new(self.builder.parent_state(), false)) + } +} + /// A builder for creating only the value column of a [`VariantArray`] /// /// This builder is used when you have existing metadata and only need to build @@ -502,8 +583,33 @@ fn binary_view_array_from_buffers(buffer: Vec, offsets: Vec) -> Binar mod test { use super::*; use crate::ShreddedSchemaBuilder; - use arrow::array::Array; - use parquet_variant::{ShortString, Variant}; + use crate::variant_array::ShreddedVariantFieldArray; + use arrow::array::{ + Array, BooleanArray, FixedSizeBinaryArray, Float64Array, Int32Array, Int64Array, ListArray, + StringArray, StructArray, + }; + use parquet_variant::{ShortString, Uuid, Variant}; + + fn typed_value(arr: &VariantArray) -> &T { + arr.typed_value_field() + .unwrap() + .as_any() + .downcast_ref::() + .unwrap() + } + + fn shredded_field(typed_value: &StructArray, name: &str) -> ShreddedVariantFieldArray { + ShreddedVariantFieldArray::try_new(typed_value.column_by_name(name).unwrap()).unwrap() + } + + fn field_typed_value(field: &ShreddedVariantFieldArray) -> &T { + field + .typed_value_field() + .unwrap() + .as_any() + .downcast_ref::() + .unwrap() + } /// Test that both the metadata and value buffers are non nullable #[test] @@ -698,11 +804,31 @@ mod test { b.append_variant(Variant::Int64(100)); b.append_null(); let arr = b.build_shredded(&DataType::Int64).unwrap(); - assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 3); + assert!(arr.typed_value_field().is_some()); assert!(!arr.is_null(0)); assert!(!arr.is_null(1)); assert!(arr.is_null(2)); + assert_eq!(arr.value(0), Variant::Int64(42)); + assert_eq!(arr.value(1), Variant::Int64(100)); + + let typed_values = typed_value::(&arr); + assert_eq!(typed_values.value(0), 42); + assert_eq!(typed_values.value(1), 100); + assert!(typed_values.is_null(2)); + } + + #[test] + fn with_shredding_schema_try_build_primitive_int64() { + let mut b = VariantArrayBuilder::new(2).with_shredding_schema(DataType::Int64); + b.append_variant(Variant::Int64(42)); + b.append_null(); + + let arr = b.try_build().unwrap(); + + assert_eq!(arr.len(), 2); + assert_eq!(arr.value(0), Variant::Int64(42)); + assert!(arr.is_null(1)); } #[test] @@ -715,16 +841,26 @@ mod test { assert_eq!(arr.len(), 2); assert!(!arr.is_null(0)); assert!(arr.is_null(1)); + assert_eq!(arr.value(0), Variant::from("hello")); + + let typed_values = typed_value::(&arr); + assert_eq!(typed_values.value(0), "hello"); + assert!(typed_values.is_null(1)); } #[test] fn build_shredded_primitive_float64() { let mut b = VariantArrayBuilder::new(2); - b.append_variant(Variant::Float(3.14)); + b.append_variant(Variant::Double(3.14)); b.append_null(); let arr = b.build_shredded(&DataType::Float64).unwrap(); assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 2); + assert_eq!(arr.value(0), Variant::Double(3.14)); + + let typed_values = typed_value::(&arr); + assert_eq!(typed_values.value(0), 3.14); + assert!(typed_values.is_null(1)); } #[test] @@ -735,6 +871,12 @@ mod test { let arr = b.build_shredded(&DataType::Boolean).unwrap(); assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 2); + assert_eq!(arr.value(0), Variant::BooleanTrue); + assert_eq!(arr.value(1), Variant::BooleanFalse); + + let typed_values = typed_value::(&arr); + assert!(typed_values.value(0)); + assert!(!typed_values.value(1)); } #[test] @@ -749,21 +891,37 @@ mod test { assert_eq!(arr.len(), 2); assert!(!arr.is_null(0)); assert!(!arr.is_null(1)); + assert_eq!(arr.value(0), Variant::Int64(7)); + assert_eq!(arr.value(1), Variant::from("not an int")); + + let value = arr.value_field().unwrap(); + let typed_values = typed_value::(&arr); + assert!(value.is_null(0)); + assert!(typed_values.is_valid(0)); + assert!(value.is_valid(1)); + assert!(typed_values.is_null(1)); } #[test] fn build_shredded_struct_single_field() { let schema = DataType::Struct(vec![Field::new("brand", DataType::Utf8, true)].into()); - let mut b = VariantArrayBuilder::new(3); + let mut b = VariantArrayBuilder::new(3).with_shredding_schema(schema); b.new_object().with_field("brand", "Apple").finish(); b.new_object().with_field("brand", "Samsung").finish(); b.append_null(); - let arr = b.build_shredded(&schema).unwrap(); + let arr = b.try_build().unwrap(); assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 3); assert!(!arr.is_null(0)); assert!(!arr.is_null(1)); assert!(arr.is_null(2)); + + let typed_struct = typed_value::(&arr); + let brand = shredded_field(typed_struct, "brand"); + let brand_typed_values = field_typed_value::(&brand); + assert_eq!(brand_typed_values.value(0), "Apple"); + assert_eq!(brand_typed_values.value(1), "Samsung"); + assert!(brand_typed_values.is_null(2)); } #[test] @@ -783,6 +941,17 @@ mod test { let arr = b.build_shredded(&schema).unwrap(); assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 2); + + let typed_struct = typed_value::(&arr); + let name = shredded_field(typed_struct, "name"); + let name_typed_values = field_typed_value::(&name); + assert_eq!(name_typed_values.value(0), "Alice"); + assert_eq!(name_typed_values.value(1), "Bob"); + + let age = shredded_field(typed_struct, "age"); + let age_typed_values = field_typed_value::(&age); + assert_eq!(age_typed_values.value(0), 30); + assert!(age_typed_values.is_null(1)); } #[test] @@ -808,6 +977,20 @@ mod test { assert_eq!(arr.len(), 2); assert!(!arr.is_null(0)); assert!(arr.is_null(1)); + + let typed_struct = typed_value::(&arr); + let address = shredded_field(typed_struct, "address"); + let address_typed_value = field_typed_value::(&address); + + let city = shredded_field(address_typed_value, "city"); + let city_typed_values = field_typed_value::(&city); + assert_eq!(city_typed_values.value(0), "NYC"); + assert!(city_typed_values.is_null(1)); + + let zip = shredded_field(address_typed_value, "zip"); + let zip_typed_values = field_typed_value::(&zip); + assert_eq!(zip_typed_values.value(0), "10001"); + assert!(zip_typed_values.is_null(1)); } #[test] @@ -826,6 +1009,19 @@ mod test { assert_eq!(arr.len(), 2); assert!(!arr.is_null(0)); assert!(arr.is_null(1)); + + let typed_list = typed_value::(&arr); + assert_eq!(typed_list.value_offsets(), &[0, 2, 2]); + assert!(typed_list.is_valid(0)); + assert!(typed_list.is_null(1)); + + let elements = ShreddedVariantFieldArray::try_new(typed_list.values().as_ref()).unwrap(); + let element_values = elements.value_field().unwrap(); + let element_typed_values = field_typed_value::(&elements); + assert!(element_values.is_null(0)); + assert!(element_values.is_null(1)); + assert_eq!(element_typed_values.value(0), 1); + assert_eq!(element_typed_values.value(1), 2); } #[test] @@ -844,6 +1040,15 @@ mod test { assert!(arr.is_null(1)); assert!(!arr.is_null(2)); assert!(!arr.is_null(3)); + assert_eq!(arr.value(0), Variant::Int64(1)); + assert_eq!(arr.value(2), Variant::Int64(3)); + assert_eq!(arr.value(3), Variant::from("oops")); + + let typed_values = typed_value::(&arr); + assert_eq!(typed_values.value(0), 1); + assert!(typed_values.is_null(1)); + assert_eq!(typed_values.value(2), 3); + assert!(typed_values.is_null(3)); } #[test] @@ -857,6 +1062,11 @@ mod test { assert!(arr.is_null(0)); assert!(arr.is_null(1)); assert!(arr.is_null(2)); + + let typed_values = typed_value::(&arr); + assert!(typed_values.is_null(0)); + assert!(typed_values.is_null(1)); + assert!(typed_values.is_null(2)); } #[test] @@ -870,10 +1080,16 @@ mod test { #[test] fn build_shredded_uuid_fixed_size_binary_16() { let uuid_bytes: Vec = (0u8..16).collect(); + let uuid = Uuid::from_slice(&uuid_bytes).unwrap(); let mut b = VariantArrayBuilder::new(1); - b.append_variant(Variant::from(uuid_bytes.as_slice())); + b.append_variant(Variant::Uuid(uuid)); let arr = b.build_shredded(&DataType::FixedSizeBinary(16)).unwrap(); assert!(arr.typed_value_field().is_some()); assert_eq!(arr.len(), 1); + + assert_eq!(arr.value(0), Variant::Uuid(uuid)); + + let typed_values = typed_value::(&arr); + assert_eq!(typed_values.value(0), uuid_bytes.as_slice()); } }