@@ -29,15 +29,16 @@ use std::ptr::NonNull;
2929///
3030/// Wrapper around `tsk_tree_t`.
3131pub struct Tree {
32- pub ( crate ) inner : ll_bindings:: tsk_tree_t ,
32+ pub ( crate ) inner : mbox :: MBox < ll_bindings:: tsk_tree_t > ,
3333 api : TreeInterface ,
3434 current_tree : i32 ,
3535 advanced : bool ,
3636}
3737
3838impl Drop for Tree {
3939 fn drop ( & mut self ) {
40- let rv = unsafe { tsk_tree_free ( & mut self . inner ) } ;
40+ // SAFETY: Mbox<_> cannot hold a NULL ptr
41+ let rv = unsafe { tsk_tree_free ( self . inner . as_mut ( ) ) } ;
4142 assert_eq ! ( rv, 0 ) ;
4243 }
4344}
@@ -58,29 +59,38 @@ impl DerefMut for Tree {
5859impl Tree {
5960 fn new < F : Into < TreeFlags > > ( ts : & TreeSequence , flags : F ) -> Result < Self , TskitError > {
6061 let flags = flags. into ( ) ;
61- let mut tree = MaybeUninit :: < ll_bindings:: tsk_tree_t > :: uninit ( ) ;
62+
63+ // SAFETY: this is the type we want :)
64+ let temp = unsafe {
65+ libc:: malloc ( std:: mem:: size_of :: < ll_bindings:: tsk_tree_t > ( ) )
66+ as * mut ll_bindings:: tsk_tree_t
67+ } ;
68+
69+ // Get our pointer into MBox ASAP
70+ let nonnull = NonNull :: < ll_bindings:: tsk_tree_t > :: new ( temp)
71+ . ok_or_else ( || TskitError :: LibraryError ( "failed to malloc tsk_tree_t" . to_string ( ) ) ) ?;
72+
73+ // SAFETY: if temp is NULL, we have returned Err already.
74+ let mut tree = unsafe { mbox:: MBox :: from_non_null_raw ( nonnull) } ;
6275 let mut rv =
63- unsafe { ll_bindings:: tsk_tree_init ( tree. as_mut_ptr ( ) , ts. as_ptr ( ) , flags. bits ( ) ) } ;
76+ unsafe { ll_bindings:: tsk_tree_init ( tree. as_mut ( ) , ts. as_ptr ( ) , flags. bits ( ) ) } ;
6477 if rv < 0 {
6578 return Err ( TskitError :: ErrorCode { code : rv } ) ;
6679 }
6780 // Gotta ask Jerome about this one--why isn't this handled in tsk_tree_init??
6881 if !flags. contains ( TreeFlags :: NO_SAMPLE_COUNTS ) {
82+ // SAFETY: nobody is null here.
6983 rv = unsafe {
7084 ll_bindings:: tsk_tree_set_tracked_samples (
71- tree. as_mut_ptr ( ) ,
85+ tree. as_mut ( ) ,
7286 ts. num_samples ( ) . into ( ) ,
73- ( * tree. as_ptr ( ) ) . samples ,
87+ ( * tree. as_mut ( ) ) . samples ,
7488 )
7589 } ;
7690 }
7791
78- let mut tree = unsafe { tree. assume_init ( ) } ;
79- let ptr = & mut tree as * mut ll_bindings:: tsk_tree_t ;
80-
8192 let num_nodes = unsafe { ( * ( * ts. as_ptr ( ) ) . tables ) . nodes . num_rows } ;
82- let non_owned_pointer = unsafe { NonNull :: new_unchecked ( ptr) } ;
83- let api = TreeInterface :: new ( non_owned_pointer, num_nodes, num_nodes + 1 , flags) ;
93+ let api = TreeInterface :: new ( nonnull, num_nodes, num_nodes + 1 , flags) ;
8494 handle_tsk_return_value ! (
8595 rv,
8696 Tree {
0 commit comments