@@ -272,26 +272,11 @@ impl VariantArray {
272272 ) ) ) ;
273273 } ;
274274
275- // Extract value and typed_value fields
276- let value = if let Some ( value_col) = inner. column_by_name ( "value" ) {
277- if let Some ( binary_view) = value_col. as_binary_view_opt ( ) {
278- Some ( binary_view. clone ( ) )
279- } else {
280- return Err ( ArrowError :: NotYetImplemented ( format ! (
281- "VariantArray 'value' field must be BinaryView, got {}" ,
282- value_col. data_type( )
283- ) ) ) ;
284- }
285- } else {
286- None
287- } ;
288- let typed_value = inner. column_by_name ( "typed_value" ) . cloned ( ) ;
289-
290275 // Note these clones are cheap, they just bump the ref count
291276 Ok ( Self {
292277 inner : inner. clone ( ) ,
293278 metadata : metadata. clone ( ) ,
294- shredding_state : ShreddingState :: new ( value , typed_value ) ,
279+ shredding_state : ShreddingState :: try_from ( inner ) ? ,
295280 } )
296281 }
297282
@@ -521,7 +506,7 @@ impl ShreddedVariantFieldArray {
521506 // Note this clone is cheap, it just bumps the ref count
522507 Ok ( Self {
523508 inner : inner_struct. clone ( ) ,
524- shredding_state : ShreddingState :: from ( inner_struct) ,
509+ shredding_state : ShreddingState :: try_from ( inner_struct) ? ,
525510 } )
526511 }
527512
@@ -660,7 +645,7 @@ impl ShreddingState {
660645 /// Create a new `ShreddingState` from the given `value` and `typed_value` fields
661646 ///
662647 /// Note you can create a `ShreddingState` from a &[`StructArray`] using
663- /// `ShreddingState::from (&struct_array)`, for example:
648+ /// `ShreddingState::try_from (&struct_array)`, for example:
664649 ///
665650 /// ```no_run
666651 /// # use arrow::array::StructArray;
@@ -669,7 +654,7 @@ impl ShreddingState {
669654 /// # unimplemented!()
670655 /// # }
671656 /// let struct_array: StructArray = get_struct_array();
672- /// let shredding_state = ShreddingState::from (&struct_array);
657+ /// let shredding_state = ShreddingState::try_from (&struct_array).unwrap( );
673658 /// ```
674659 pub fn new ( value : Option < BinaryViewArray > , typed_value : Option < ArrayRef > ) -> Self {
675660 Self { value, typed_value }
@@ -685,6 +670,14 @@ impl ShreddingState {
685670 self . typed_value . as_ref ( )
686671 }
687672
673+ /// Returns a borrowed version of this shredding state
674+ pub fn borrow ( & self ) -> BorrowedShreddingState < ' _ > {
675+ BorrowedShreddingState {
676+ value : self . value_field ( ) ,
677+ typed_value : self . typed_value_field ( ) ,
678+ }
679+ }
680+
688681 /// Slice all the underlying arrays
689682 pub fn slice ( & self , offset : usize , length : usize ) -> Self {
690683 Self {
@@ -694,14 +687,79 @@ impl ShreddingState {
694687 }
695688}
696689
697- impl From < & StructArray > for ShreddingState {
698- fn from ( inner_struct : & StructArray ) -> Self {
699- let value = inner_struct
700- . column_by_name ( "value" )
701- . and_then ( |col| col. as_binary_view_opt ( ) . cloned ( ) ) ;
702- let typed_value = inner_struct. column_by_name ( "typed_value" ) . cloned ( ) ;
690+ /// Similar to [`ShreddingState`] except it holds borrowed references of the target arrays. Useful
691+ /// for avoiding clone operations when the caller does not need a self-standing shredding state.
692+ #[ derive( Clone , Debug ) ]
693+ pub struct BorrowedShreddingState < ' a > {
694+ value : Option < & ' a BinaryViewArray > ,
695+ typed_value : Option < & ' a ArrayRef > ,
696+ }
703697
704- ShreddingState :: new ( value, typed_value)
698+ impl < ' a > BorrowedShreddingState < ' a > {
699+ /// Create a new `BorrowedShreddingState` from the given `value` and `typed_value` fields
700+ ///
701+ /// Note you can create a `BorrowedShreddingState` from a &[`StructArray`] using
702+ /// `BorrowedShreddingState::try_from(&struct_array)`, for example:
703+ ///
704+ /// ```no_run
705+ /// # use arrow::array::StructArray;
706+ /// # use parquet_variant_compute::BorrowedShreddingState;
707+ /// # fn get_struct_array() -> StructArray {
708+ /// # unimplemented!()
709+ /// # }
710+ /// let struct_array: StructArray = get_struct_array();
711+ /// let shredding_state = BorrowedShreddingState::try_from(&struct_array).unwrap();
712+ /// ```
713+ pub fn new ( value : Option < & ' a BinaryViewArray > , typed_value : Option < & ' a ArrayRef > ) -> Self {
714+ Self { value, typed_value }
715+ }
716+
717+ /// Return a reference to the value field, if present
718+ pub fn value_field ( & self ) -> Option < & ' a BinaryViewArray > {
719+ self . value
720+ }
721+
722+ /// Return a reference to the typed_value field, if present
723+ pub fn typed_value_field ( & self ) -> Option < & ' a ArrayRef > {
724+ self . typed_value
725+ }
726+ }
727+
728+ impl < ' a > TryFrom < & ' a StructArray > for BorrowedShreddingState < ' a > {
729+ type Error = ArrowError ;
730+
731+ fn try_from ( inner_struct : & ' a StructArray ) -> Result < Self , ArrowError > {
732+ // The `value` column need not exist, but if it does it must be a binary view.
733+ let value = if let Some ( value_col) = inner_struct. column_by_name ( "value" ) {
734+ let Some ( binary_view) = value_col. as_binary_view_opt ( ) else {
735+ return Err ( ArrowError :: NotYetImplemented ( format ! (
736+ "VariantArray 'value' field must be BinaryView, got {}" ,
737+ value_col. data_type( )
738+ ) ) ) ;
739+ } ;
740+ Some ( binary_view)
741+ } else {
742+ None
743+ } ;
744+ let typed_value = inner_struct. column_by_name ( "typed_value" ) ;
745+ Ok ( BorrowedShreddingState :: new ( value, typed_value) )
746+ }
747+ }
748+
749+ impl TryFrom < & StructArray > for ShreddingState {
750+ type Error = ArrowError ;
751+
752+ fn try_from ( inner_struct : & StructArray ) -> Result < Self , ArrowError > {
753+ Ok ( BorrowedShreddingState :: try_from ( inner_struct) ?. into ( ) )
754+ }
755+ }
756+
757+ impl From < BorrowedShreddingState < ' _ > > for ShreddingState {
758+ fn from ( state : BorrowedShreddingState < ' _ > ) -> Self {
759+ ShreddingState {
760+ value : state. value_field ( ) . cloned ( ) ,
761+ typed_value : state. typed_value_field ( ) . cloned ( ) ,
762+ }
705763 }
706764}
707765
0 commit comments