Skip to content

Commit db32eef

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

File tree

1 file changed

+48
-91
lines changed

1 file changed

+48
-91
lines changed

parquet-variant/src/builder.rs

Lines changed: 48 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717
use crate::decoder::{VariantBasicType, VariantPrimitiveType};
18-
use crate::{
19-
ShortString, Variant, VariantDecimal16, VariantDecimal4, VariantDecimal8, VariantList,
20-
VariantObject,
21-
};
18+
use crate::{ShortString, Variant, VariantDecimal16, VariantDecimal4, VariantDecimal8};
2219
use arrow_schema::ArrowError;
2320
use indexmap::{IndexMap, IndexSet};
2421
use std::collections::HashSet;
@@ -195,7 +192,32 @@ impl ValueBuffer {
195192
self.0.len()
196193
}
197194

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

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-
226259
/// Writes out the header byte for a variant object or list
227260
fn append_header(&mut self, header_byte: u8, is_large: bool, num_items: usize) {
228261
let buf = self.inner_mut();
@@ -699,79 +732,6 @@ impl VariantBuilder {
699732
ObjectBuilder::new(parent_state, validate_unique_fields)
700733
}
701734

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-
775735
/// Append a non-nested value to the builder.
776736
///
777737
/// # Example
@@ -783,12 +743,8 @@ impl VariantBuilder {
783743
/// ```
784744
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
785745
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-
}
746+
self.buffer
747+
.append_variant(variant, &mut self.metadata_builder);
792748
}
793749

794750
/// Finish the builder and return the metadata and value buffers.
@@ -855,7 +811,8 @@ impl<'a> ListBuilder<'a> {
855811
/// Appends a new primitive value to this list
856812
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
857813
self.offsets.push(self.buffer.offset());
858-
self.buffer.append_non_nested_value(value);
814+
self.buffer
815+
.append_variant(value.into(), self.parent_state.metadata_builder())
859816
}
860817

861818
/// Finalizes this list and appends it to its parent, which otherwise remains unmodified.
@@ -927,7 +884,7 @@ impl<'a> ObjectBuilder<'a> {
927884
self.duplicate_fields.insert(field_id);
928885
}
929886

930-
self.buffer.append_non_nested_value(value);
887+
self.buffer.append_variant(value.into(), metadata_builder)
931888
}
932889

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

0 commit comments

Comments
 (0)