@@ -22,6 +22,7 @@ use arrow::array::{ArrayRef, BinaryViewArray, BinaryViewBuilder, NullBufferBuild
22
22
use arrow_schema:: { ArrowError , DataType , Field , Fields } ;
23
23
use parquet_variant:: {
24
24
BuilderSpecificState , ListBuilder , MetadataBuilder , ObjectBuilder , Variant , VariantBuilderExt ,
25
+ VariantMetadata ,
25
26
} ;
26
27
use parquet_variant:: {
27
28
ParentState , ReadOnlyMetadataBuilder , ValueBuilder , WritableMetadataBuilder ,
@@ -294,8 +295,8 @@ impl VariantValueArrayBuilder {
294
295
/// builder.append_value(Variant::from(42));
295
296
/// ```
296
297
pub fn append_value ( & mut self , value : Variant < ' _ , ' _ > ) {
297
- let mut metadata_builder = ReadOnlyMetadataBuilder :: new ( value. metadata ( ) . clone ( ) ) ;
298
- ValueBuilder :: append_variant_bytes ( self . parent_state ( & mut metadata_builder ) , value) ;
298
+ self . builder_ext ( value. metadata ( ) . clone ( ) )
299
+ . append_value ( value) ;
299
300
}
300
301
301
302
/// Creates a builder-specific parent state.
@@ -333,6 +334,18 @@ impl VariantValueArrayBuilder {
333
334
334
335
ParentState :: new ( & mut self . value_builder , metadata_builder, state)
335
336
}
337
+
338
+ /// Creates a thin [`VariantBuilderExt`] wrapper for this builder, which hides the `metadata`
339
+ /// parameter (similar to the way [`parquet_variant::ObjectFieldBuilder`] hides field names).
340
+ pub fn builder_ext < ' a > (
341
+ & ' a mut self ,
342
+ metadata : VariantMetadata < ' a > ,
343
+ ) -> VariantValueArrayBuilderExt < ' a > {
344
+ VariantValueArrayBuilderExt {
345
+ metadata_builder : ReadOnlyMetadataBuilder :: new ( metadata) ,
346
+ value_builder : self ,
347
+ }
348
+ }
336
349
}
337
350
338
351
/// Builder-specific state for array building that manages array-level offsets and nulls. See
@@ -355,6 +368,52 @@ impl BuilderSpecificState for ValueArrayBuilderState<'_> {
355
368
}
356
369
}
357
370
371
+ /// A thin [`VariantBuilderExt`] wrapper that hides the short-lived (per-row)
372
+ /// [`ReadOnlyMetadataBuilder`] instances that [`VariantValueArrayBuilder`] requires.
373
+ pub struct VariantValueArrayBuilderExt < ' a > {
374
+ metadata_builder : ReadOnlyMetadataBuilder < ' a > ,
375
+ value_builder : & ' a mut VariantValueArrayBuilder ,
376
+ }
377
+
378
+ impl < ' a > VariantValueArrayBuilderExt < ' a > {
379
+ /// Creates a new instance from a metadata builder and a reference to a variant value builder.
380
+ pub fn new (
381
+ metadata_builder : ReadOnlyMetadataBuilder < ' a > ,
382
+ value_builder : & ' a mut VariantValueArrayBuilder ,
383
+ ) -> Self {
384
+ Self {
385
+ metadata_builder,
386
+ value_builder,
387
+ }
388
+ }
389
+ }
390
+
391
+ impl < ' a > VariantBuilderExt for VariantValueArrayBuilderExt < ' a > {
392
+ type State < ' b >
393
+ = ValueArrayBuilderState < ' b >
394
+ where
395
+ Self : ' b ;
396
+
397
+ fn append_null ( & mut self ) {
398
+ self . value_builder . append_null ( )
399
+ }
400
+
401
+ fn append_value < ' m , ' v > ( & mut self , value : impl Into < Variant < ' m , ' v > > ) {
402
+ let state = self . value_builder . parent_state ( & mut self . metadata_builder ) ;
403
+ ValueBuilder :: append_variant_bytes ( state, value. into ( ) ) ;
404
+ }
405
+
406
+ fn try_new_list ( & mut self ) -> Result < ListBuilder < ' _ , Self :: State < ' _ > > , ArrowError > {
407
+ let state = self . value_builder . parent_state ( & mut self . metadata_builder ) ;
408
+ Ok ( ListBuilder :: new ( state, false ) )
409
+ }
410
+
411
+ fn try_new_object ( & mut self ) -> Result < ObjectBuilder < ' _ , Self :: State < ' _ > > , ArrowError > {
412
+ let state = self . value_builder . parent_state ( & mut self . metadata_builder ) ;
413
+ Ok ( ObjectBuilder :: new ( state, false ) )
414
+ }
415
+ }
416
+
358
417
fn binary_view_array_from_buffers ( buffer : Vec < u8 > , offsets : Vec < usize > ) -> BinaryViewArray {
359
418
// All offsets are less than or equal to the buffer length, so we can safely cast all offsets
360
419
// inside the loop below, as long as the buffer length fits in u32.
@@ -482,32 +541,32 @@ mod test {
482
541
//
483
542
// NOTE: Because we will reuse the metadata column, we cannot reorder rows. We can only
484
543
// filter or manipulate values within a row.
485
- let mut builder = VariantValueArrayBuilder :: new ( 3 ) ;
544
+ let mut value_builder = VariantValueArrayBuilder :: new ( 3 ) ;
486
545
487
546
// straight copy
488
- builder . append_value ( array. value ( 0 ) ) ;
547
+ value_builder . append_value ( array. value ( 0 ) ) ;
489
548
490
549
// filtering fields takes more work because we need to manually create an object builder
491
550
let value = array. value ( 1 ) ;
492
- let mut metadata_builder = ReadOnlyMetadataBuilder :: new ( value. metadata ( ) . clone ( ) ) ;
493
- let state = builder. parent_state ( & mut metadata_builder ) ;
494
- ObjectBuilder :: new ( state , false )
551
+ let mut builder = value_builder . builder_ext ( value. metadata ( ) . clone ( ) ) ;
552
+ builder
553
+ . new_object ( )
495
554
. with_field ( "name" , value. get_object_field ( "name" ) . unwrap ( ) )
496
555
. with_field ( "age" , value. get_object_field ( "age" ) . unwrap ( ) )
497
556
. finish ( ) ;
498
557
499
558
// same bytes, but now nested and duplicated inside a list
500
559
let value = array. value ( 2 ) ;
501
- let mut metadata_builder = ReadOnlyMetadataBuilder :: new ( value. metadata ( ) . clone ( ) ) ;
502
- let state = builder. parent_state ( & mut metadata_builder ) ;
503
- ListBuilder :: new ( state , false )
560
+ let mut builder = value_builder . builder_ext ( value. metadata ( ) . clone ( ) ) ;
561
+ builder
562
+ . new_list ( )
504
563
. with_value ( value. clone ( ) )
505
564
. with_value ( value. clone ( ) )
506
565
. finish ( ) ;
507
566
508
567
let array2 = VariantArray :: from_parts (
509
568
array. metadata_field ( ) . clone ( ) ,
510
- Some ( builder . build ( ) . unwrap ( ) ) ,
569
+ Some ( value_builder . build ( ) . unwrap ( ) ) ,
511
570
None ,
512
571
None ,
513
572
) ;
0 commit comments