Skip to content

Commit 055f77a

Browse files
committed
refactor: Tree now stores tsk_tree_t in MBox.
1 parent 82dd4a1 commit 055f77a

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

src/trees.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@ use std::ptr::NonNull;
2929
///
3030
/// Wrapper around `tsk_tree_t`.
3131
pub 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

3838
impl 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 {
5859
impl 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

Comments
 (0)