Skip to content

Commit 014ffad

Browse files
Merge pull request #5 from alamb/alamb/suggestions_complex
Unify nested variant handling
2 parents 4dc7f30 + 28832d5 commit 014ffad

File tree

1 file changed

+42
-89
lines changed

1 file changed

+42
-89
lines changed

parquet-variant/src/builder.rs

Lines changed: 42 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
// under the License.
1717
use crate::decoder::{VariantBasicType, VariantPrimitiveType};
1818
use crate::{
19-
ShortString, Variant, VariantDecimal16, VariantDecimal4, VariantDecimal8, VariantList,
20-
VariantObject,
19+
ShortString, Variant, VariantDecimal16, VariantDecimal4, VariantDecimal8,
2120
};
2221
use arrow_schema::ArrowError;
2322
use indexmap::{IndexMap, IndexSet};
@@ -195,7 +194,28 @@ impl ValueBuffer {
195194
self.0.len()
196195
}
197196

198-
fn append_variant<'m, 'd>(&mut self, variant: Variant<'m, 'd>) {
197+
fn new_object<'a>(&'a mut self, metadata_builder: &'a mut MetadataBuilder) -> ObjectBuilder<'a> {
198+
let parent_state = ParentState::Variant {
199+
buffer: self,
200+
metadata_builder,
201+
};
202+
let validate_unique_fields = false;
203+
ObjectBuilder::new(parent_state, validate_unique_fields)
204+
}
205+
206+
fn new_list<'a>(
207+
&'a mut self,
208+
metadata_builder: &'a mut MetadataBuilder,
209+
) -> ListBuilder<'a> {
210+
let parent_state = ParentState::Variant {
211+
buffer: self,
212+
metadata_builder,
213+
};
214+
let validate_unique_fields = false;
215+
ListBuilder::new(parent_state, validate_unique_fields)
216+
}
217+
218+
fn append_variant<'m, 'd>(&mut self, variant: Variant<'m, 'd>, metadata_builder: &mut MetadataBuilder) {
199219
match variant {
200220
Variant::Null => self.append_null(),
201221
Variant::BooleanTrue => self.append_bool(true),
@@ -215,14 +235,25 @@ impl ValueBuffer {
215235
Variant::Binary(v) => self.append_binary(v),
216236
Variant::String(s) => self.append_string(s),
217237
Variant::ShortString(s) => self.append_short_string(s),
218-
_ => unreachable!("Objects and lists must be appended using VariantBuilder::append_object and VariantBuilder::append_list"),
238+
Variant::Object(obj) => {
239+
let mut object_builder = self.new_object(metadata_builder);
240+
for (field_name, value) in obj.iter() {
241+
object_builder.insert(field_name, value);
242+
}
243+
// TODO propagate error
244+
object_builder.finish().unwrap();
245+
}
246+
Variant::List(list) => {
247+
let mut list_builder = self.new_list(metadata_builder);
248+
for value in list.iter() {
249+
list_builder.append_value(value);
250+
}
251+
// TOOD propagate error
252+
list_builder.finish();
253+
}
219254
}
220255
}
221256

222-
fn append_non_nested_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
223-
self.append_variant(value.into());
224-
}
225-
226257
/// Writes out the header byte for a variant object or list
227258
fn append_header(&mut self, header_byte: u8, is_large: bool, num_items: usize) {
228259
let buf = self.inner_mut();
@@ -699,79 +730,6 @@ impl VariantBuilder {
699730
ObjectBuilder::new(parent_state, validate_unique_fields)
700731
}
701732

702-
/// Appends a [`VariantObject`] to the builder.
703-
///
704-
/// # Panics
705-
/// Will panic if the appended object has duplicate field names or any nested validation fails.
706-
/// Use `try_append_object` if you need full validation for untrusted data.
707-
pub fn append_object<'m, 'v>(&mut self, object: VariantObject<'m, 'v>) {
708-
let (parent_state, validate_unique_fields) = self.parent_state();
709-
710-
let mut obj_builder = ObjectBuilder::new(parent_state, validate_unique_fields);
711-
712-
for (field_name, variant) in object.iter() {
713-
obj_builder.insert(field_name, variant);
714-
}
715-
716-
obj_builder.finish().unwrap();
717-
}
718-
719-
/// Appends a [`VariantObject`] to the builder with full validation during iteration.
720-
///
721-
/// Recursively validates all nested variants in the object during iteration.
722-
pub fn try_append_object<'m, 'v>(
723-
&mut self,
724-
object: VariantObject<'m, 'v>,
725-
) -> Result<(), ArrowError> {
726-
let (parent_state, validate_unique_fields) = self.parent_state();
727-
728-
let mut obj_builder = ObjectBuilder::new(parent_state, validate_unique_fields);
729-
730-
for res in object.iter_try() {
731-
let (field_name, variant) = res?;
732-
733-
obj_builder.insert(field_name, variant);
734-
}
735-
736-
obj_builder.finish()?;
737-
738-
Ok(())
739-
}
740-
741-
/// Appends a [`VariantList`] to the builder.
742-
///
743-
/// # Panics
744-
/// Will panic if any nested validation fails during list iteration.
745-
/// Use `try_append_list` if you need full validation for untrusted data.
746-
pub fn append_list<'m, 'v>(&mut self, list: VariantList<'m, 'v>) {
747-
let (parent_state, validate_unique_fields) = self.parent_state();
748-
749-
let mut list_builder = ListBuilder::new(parent_state, validate_unique_fields);
750-
751-
for variant in list.iter() {
752-
list_builder.append_value(variant);
753-
}
754-
755-
list_builder.finish();
756-
}
757-
758-
/// Appends a [`VariantList`] to the builder with full validation during iteration.
759-
///
760-
/// Recursively validates all nested variants in the list during iteration.
761-
pub fn try_append_list<'m, 'v>(&mut self, list: VariantList<'m, 'v>) -> Result<(), ArrowError> {
762-
let (parent_state, validate_unique_fields) = self.parent_state();
763-
764-
let mut list_builder = ListBuilder::new(parent_state, validate_unique_fields);
765-
766-
for variant in list.iter_try() {
767-
list_builder.append_value(variant?);
768-
}
769-
770-
list_builder.finish();
771-
772-
Ok(())
773-
}
774-
775733
/// Append a non-nested value to the builder.
776734
///
777735
/// # Example
@@ -783,12 +741,7 @@ impl VariantBuilder {
783741
/// ```
784742
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
785743
let variant = value.into();
786-
787-
match variant {
788-
Variant::Object(obj) => self.append_object(obj),
789-
Variant::List(list) => self.append_list(list),
790-
primitive => self.buffer.append_variant(primitive),
791-
}
744+
self.buffer.append_variant(variant, &mut self.metadata_builder);
792745
}
793746

794747
/// Finish the builder and return the metadata and value buffers.
@@ -855,7 +808,7 @@ impl<'a> ListBuilder<'a> {
855808
/// Appends a new primitive value to this list
856809
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
857810
self.offsets.push(self.buffer.offset());
858-
self.buffer.append_non_nested_value(value);
811+
self.buffer.append_variant(value.into(), self.parent_state.metadata_builder())
859812
}
860813

861814
/// Finalizes this list and appends it to its parent, which otherwise remains unmodified.
@@ -927,7 +880,7 @@ impl<'a> ObjectBuilder<'a> {
927880
self.duplicate_fields.insert(field_id);
928881
}
929882

930-
self.buffer.append_non_nested_value(value);
883+
self.buffer.append_variant(value.into(), metadata_builder)
931884
}
932885

933886
/// Enables validation for unique field keys when inserting into this object.

0 commit comments

Comments
 (0)