Skip to content

Commit bd081db

Browse files
authored
refactor: remove internal ffi module (#310)
1 parent 8cc8ed1 commit bd081db

File tree

5 files changed

+63
-142
lines changed

5 files changed

+63
-142
lines changed

src/_macros.rs

-45
Original file line numberDiff line numberDiff line change
@@ -127,51 +127,6 @@ macro_rules! unsafe_tsk_ragged_char_column_access {
127127
}};
128128
}
129129

130-
macro_rules! drop_for_tskit_type {
131-
($name: ident, $drop: ident) => {
132-
impl Drop for $name {
133-
fn drop(&mut self) {
134-
let rv = unsafe { $drop(&mut *self.inner) };
135-
panic_on_tskit_error!(rv);
136-
}
137-
}
138-
};
139-
}
140-
141-
macro_rules! tskit_type_access {
142-
($name: ident, $ll_name: ty) => {
143-
impl $crate::TskitTypeAccess<$ll_name> for $name {
144-
fn as_ptr(&self) -> *const $ll_name {
145-
&*self.inner
146-
}
147-
148-
fn as_mut_ptr(&mut self) -> *mut $ll_name {
149-
&mut *self.inner
150-
}
151-
}
152-
};
153-
}
154-
155-
macro_rules! build_tskit_type {
156-
($name: ident, $ll_name: ty, $drop: ident) => {
157-
impl $crate::ffi::WrapTskitType<$ll_name> for $name {
158-
fn wrap() -> Self {
159-
use mbox::MBox;
160-
let temp =
161-
unsafe { libc::malloc(std::mem::size_of::<$ll_name>()) as *mut $ll_name };
162-
let nonnull = match std::ptr::NonNull::<$ll_name>::new(temp) {
163-
Some(x) => x,
164-
None => panic!("out of memory"),
165-
};
166-
let mbox = unsafe { MBox::from_non_null_raw(nonnull) };
167-
$name { inner: mbox }
168-
}
169-
}
170-
drop_for_tskit_type!($name, $drop);
171-
tskit_type_access!($name, $ll_name);
172-
};
173-
}
174-
175130
macro_rules! metadata_to_vector {
176131
($outer: ident, $table: expr, $row: expr) => {
177132
$crate::metadata::char_column_to_slice(

src/ffi.rs

-60
This file was deleted.

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ pub mod bindings;
8080
mod _macros; // Starts w/_ to be sorted at front by rustfmt!
8181
mod edge_table;
8282
pub mod error;
83-
mod ffi;
8483
mod flags;
8584
mod individual_table;
8685
pub mod metadata;

src/table_collection.rs

+47-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::bindings as ll_bindings;
22
use crate::error::TskitError;
3-
use crate::ffi::WrapTskitType;
43
use crate::types::Bookmark;
54
use crate::EdgeTable;
65
use crate::IndividualTable;
@@ -60,14 +59,38 @@ use mbox::MBox;
6059
/// ```
6160
///
6261
pub struct TableCollection {
63-
pub(crate) inner: MBox<ll_bindings::tsk_table_collection_t>,
62+
inner: MBox<ll_bindings::tsk_table_collection_t>,
6463
}
6564

66-
build_tskit_type!(
67-
TableCollection,
68-
ll_bindings::tsk_table_collection_t,
69-
tsk_table_collection_free
70-
);
65+
impl TskitTypeAccess<ll_bindings::tsk_table_collection_t> for TableCollection {
66+
fn as_ptr(&self) -> *const ll_bindings::tsk_table_collection_t {
67+
&*self.inner
68+
}
69+
70+
fn as_mut_ptr(&mut self) -> *mut ll_bindings::tsk_table_collection_t {
71+
&mut *self.inner
72+
}
73+
}
74+
75+
impl Drop for TableCollection {
76+
fn drop(&mut self) {
77+
let rv = unsafe { tsk_table_collection_free(self.as_mut_ptr()) };
78+
assert_eq!(rv, 0);
79+
}
80+
}
81+
82+
/// Returns a pointer to an uninitialized tsk_table_collection_t
83+
pub(crate) fn uninit_table_collection() -> MBox<ll_bindings::tsk_table_collection_t> {
84+
let temp = unsafe {
85+
libc::malloc(std::mem::size_of::<ll_bindings::tsk_table_collection_t>())
86+
as *mut ll_bindings::tsk_table_collection_t
87+
};
88+
let nonnull = match std::ptr::NonNull::<ll_bindings::tsk_table_collection_t>::new(temp) {
89+
Some(x) => x,
90+
None => panic!("out of memory"),
91+
};
92+
unsafe { MBox::from_non_null_raw(nonnull) }
93+
}
7194

7295
impl TableCollection {
7396
/// Create a new table collection with a sequence length.
@@ -91,19 +114,27 @@ impl TableCollection {
91114
expected: "sequence_length >= 0.0".to_string(),
92115
});
93116
}
94-
let mut tables = Self::wrap();
95-
let rv = unsafe { ll_bindings::tsk_table_collection_init(tables.as_mut_ptr(), 0) };
117+
let mut mbox = uninit_table_collection();
118+
let rv = unsafe { ll_bindings::tsk_table_collection_init(&mut *mbox, 0) };
96119
if rv < 0 {
97120
return Err(crate::error::TskitError::ErrorCode { code: rv });
98121
}
122+
let mut tables = Self { inner: mbox };
99123
unsafe {
100124
(*tables.as_mut_ptr()).sequence_length = sequence_length.0;
101125
}
102126
Ok(tables)
103127
}
104128

105-
pub(crate) fn new_uninit() -> Self {
106-
Self::wrap()
129+
/// # Safety
130+
///
131+
/// It is possible that the mbox's inner pointer has not be run through
132+
/// tsk_table_collection_init, meaning that it is in an uninitialized state.
133+
/// Or, it may be initialized and about to be used in a part of the C API
134+
/// requiring an uninitialized table collection.
135+
/// Consult the C API docs before using!
136+
pub(crate) unsafe fn new_from_mbox(mbox: MBox<ll_bindings::tsk_table_collection_t>) -> Self {
137+
Self { inner: mbox }
107138
}
108139

109140
pub(crate) fn into_raw(self) -> Result<*mut ll_bindings::tsk_table_collection_t, TskitError> {
@@ -694,12 +725,13 @@ impl TableCollection {
694725
pub fn deepcopy(&self) -> Result<TableCollection, TskitError> {
695726
// The output is UNINITIALIZED tables,
696727
// else we leak memory
697-
let mut copy = Self::new_uninit();
728+
let mut inner = uninit_table_collection();
698729

699-
let rv =
700-
unsafe { ll_bindings::tsk_table_collection_copy(self.as_ptr(), copy.as_mut_ptr(), 0) };
730+
let rv = unsafe { ll_bindings::tsk_table_collection_copy(self.as_ptr(), &mut *inner, 0) };
701731

702-
handle_tsk_return_value!(rv, copy)
732+
// SAFETY: we just initialized it.
733+
// The C API doesn't free NULL pointers.
734+
handle_tsk_return_value!(rv, unsafe { Self::new_from_mbox(inner) })
703735
}
704736

705737
/// Return a [`crate::TreeSequence`] based on the tables.

src/trees.rs

+16-21
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::ops::DerefMut;
44

55
use crate::bindings as ll_bindings;
66
use crate::error::TskitError;
7-
use crate::ffi::WrapTskitType;
87
use crate::EdgeTable;
98
use crate::IndividualTable;
109
use crate::MigrationTable;
@@ -167,14 +166,6 @@ pub struct TreeSequence {
167166
pub(crate) inner: ll_bindings::tsk_treeseq_t,
168167
}
169168

170-
impl crate::ffi::WrapTskitType<ll_bindings::tsk_treeseq_t> for TreeSequence {
171-
fn wrap() -> Self {
172-
let inner = std::mem::MaybeUninit::<ll_bindings::tsk_treeseq_t>::uninit();
173-
let inner = unsafe { inner.assume_init() };
174-
Self { inner }
175-
}
176-
}
177-
178169
unsafe impl Send for TreeSequence {}
179170
unsafe impl Sync for TreeSequence {}
180171

@@ -243,17 +234,16 @@ impl TreeSequence {
243234
tables: TableCollection,
244235
flags: F,
245236
) -> Result<Self, TskitError> {
246-
let mut treeseq = Self::wrap();
237+
let mut inner = std::mem::MaybeUninit::<ll_bindings::tsk_treeseq_t>::uninit();
247238
let mut flags: u32 = flags.into().bits();
248239
flags |= ll_bindings::TSK_TAKE_OWNERSHIP;
249240
let raw_tables_ptr = tables.into_raw()?;
250241
let rv =
251-
unsafe { ll_bindings::tsk_treeseq_init(treeseq.as_mut_ptr(), raw_tables_ptr, flags) };
252-
handle_tsk_return_value!(rv, treeseq)
253-
}
254-
255-
fn new_uninit() -> Self {
256-
Self::wrap()
242+
unsafe { ll_bindings::tsk_treeseq_init(inner.as_mut_ptr(), raw_tables_ptr, flags) };
243+
handle_tsk_return_value!(rv, {
244+
let inner = unsafe { inner.assume_init() };
245+
Self { inner }
246+
})
257247
}
258248

259249
/// Dump the tree sequence to file.
@@ -294,13 +284,15 @@ impl TreeSequence {
294284
///
295285
/// [`TskitError`] will be raised if the underlying C library returns an error code.
296286
pub fn dump_tables(&self) -> Result<TableCollection, TskitError> {
297-
let mut copy = TableCollection::new_uninit();
287+
let mut inner = crate::table_collection::uninit_table_collection();
298288

299289
let rv = unsafe {
300-
ll_bindings::tsk_table_collection_copy((*self.as_ptr()).tables, copy.as_mut_ptr(), 0)
290+
ll_bindings::tsk_table_collection_copy((*self.as_ptr()).tables, &mut *inner, 0)
301291
};
302292

303-
handle_tsk_return_value!(rv, copy)
293+
// SAFETY: we just initialized it.
294+
// The C API doesn't free NULL pointers.
295+
handle_tsk_return_value!(rv, unsafe { TableCollection::new_from_mbox(inner) })
304296
}
305297

306298
/// Create an iterator over trees.
@@ -428,7 +420,7 @@ impl TreeSequence {
428420
) -> Result<(Self, Option<Vec<NodeId>>), TskitError> {
429421
// The output is an UNINITIALIZED treeseq,
430422
// else we leak memory.
431-
let mut ts = Self::new_uninit();
423+
let mut ts = MaybeUninit::<ll_bindings::tsk_treeseq_t>::uninit();
432424
let mut output_node_map: Vec<NodeId> = vec![];
433425
if idmap {
434426
output_node_map.resize(usize::try_from(self.nodes().num_rows())?, NodeId::NULL);
@@ -450,7 +442,10 @@ impl TreeSequence {
450442
handle_tsk_return_value!(
451443
rv,
452444
(
453-
ts,
445+
{
446+
let inner = unsafe { ts.assume_init() };
447+
Self { inner }
448+
},
454449
match idmap {
455450
true => Some(output_node_map),
456451
false => None,

0 commit comments

Comments
 (0)