@@ -732,14 +732,35 @@ impl OwnedDynValue {
732
732
Self { tp, buf }
733
733
}
734
734
735
- #[ doc( hidden) ]
736
- /// Use this if the values should still be used after the buffer has been
737
- /// copied to the concrete type
738
- pub fn drop_nonrecursive ( mut self ) {
739
- // We can't take ownership of the contents of self,
740
- // but we can replace the items with a zero-sized object
741
- self . tp = <[ u8 ; 0 ] as H5Type >:: type_descriptor ( ) ;
742
- self . buf = Box :: new ( [ ] ) ;
735
+ /// Cast to the concrete type
736
+ ///
737
+ /// Will fail if the type-descriptors are not equal
738
+ pub fn cast < T : H5Type > ( mut self ) -> Result < T , Self > {
739
+ use std:: mem:: MaybeUninit ;
740
+ if self . tp != T :: type_descriptor ( ) {
741
+ return Err ( self ) ;
742
+ }
743
+ debug_assert_eq ! ( self . tp. size( ) , self . buf. len( ) ) ;
744
+ let mut out = MaybeUninit :: < T > :: uninit ( ) ;
745
+ unsafe {
746
+ ptr:: copy_nonoverlapping (
747
+ self . buf . as_ptr ( ) ,
748
+ out. as_mut_ptr ( ) . cast :: < u8 > ( ) ,
749
+ self . buf . len ( ) ,
750
+ ) ;
751
+ }
752
+ // For safety we must ensure any nested structures are not live at the same time,
753
+ // as this could cause a double free in `dyn_drop`.
754
+ // We must deallocate only the top level of Self
755
+
756
+ // The zero-sized array has a special case to not drop ptr if len is zero,
757
+ // so `dyn_drop` of `DynArray` is a nop
758
+ self . tp = <[ u8 ; 0 ] >:: type_descriptor ( ) ;
759
+ // We must also swap out the buffer to ensure we can create the `DynValue`
760
+ let mut b: Box < [ u8 ] > = Box :: new ( [ ] ) ;
761
+ std:: mem:: swap ( & mut self . buf , & mut b) ;
762
+
763
+ Ok ( unsafe { out. assume_init ( ) } )
743
764
}
744
765
}
745
766
0 commit comments