@@ -29,15 +29,16 @@ use std::ptr::NonNull;
29
29
///
30
30
/// Wrapper around `tsk_tree_t`.
31
31
pub struct Tree {
32
- pub ( crate ) inner : ll_bindings:: tsk_tree_t ,
32
+ pub ( crate ) inner : mbox :: MBox < ll_bindings:: tsk_tree_t > ,
33
33
api : TreeInterface ,
34
34
current_tree : i32 ,
35
35
advanced : bool ,
36
36
}
37
37
38
38
impl Drop for Tree {
39
39
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 ( ) ) } ;
41
42
assert_eq ! ( rv, 0 ) ;
42
43
}
43
44
}
@@ -58,29 +59,38 @@ impl DerefMut for Tree {
58
59
impl Tree {
59
60
fn new < F : Into < TreeFlags > > ( ts : & TreeSequence , flags : F ) -> Result < Self , TskitError > {
60
61
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) } ;
62
75
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 ( ) ) } ;
64
77
if rv < 0 {
65
78
return Err ( TskitError :: ErrorCode { code : rv } ) ;
66
79
}
67
80
// Gotta ask Jerome about this one--why isn't this handled in tsk_tree_init??
68
81
if !flags. contains ( TreeFlags :: NO_SAMPLE_COUNTS ) {
82
+ // SAFETY: nobody is null here.
69
83
rv = unsafe {
70
84
ll_bindings:: tsk_tree_set_tracked_samples (
71
- tree. as_mut_ptr ( ) ,
85
+ tree. as_mut ( ) ,
72
86
ts. num_samples ( ) . into ( ) ,
73
- ( * tree. as_ptr ( ) ) . samples ,
87
+ ( * tree. as_mut ( ) ) . samples ,
74
88
)
75
89
} ;
76
90
}
77
91
78
- let mut tree = unsafe { tree. assume_init ( ) } ;
79
- let ptr = & mut tree as * mut ll_bindings:: tsk_tree_t ;
80
-
81
92
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) ;
84
94
handle_tsk_return_value ! (
85
95
rv,
86
96
Tree {
0 commit comments