Skip to content

Commit 93c43aa

Browse files
committed
Add trait to define what it means to wrap a tskit type.
1 parent 64ac8a0 commit 93c43aa

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

src/_macros.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,34 @@ macro_rules! unsafe_tsk_column_access {
3030
}};
3131
}
3232

33+
macro_rules! build_tskit_type {
34+
($name: ident, $ll_name: ty, $drop: ident) => {
35+
impl Drop for $name {
36+
fn drop(&mut self) {
37+
let rv = unsafe { $drop(&mut *self.inner) };
38+
panic_on_tskit_error!(rv);
39+
}
40+
}
41+
42+
impl crate::ffi::TskitType<$ll_name> for $name {
43+
fn wrap() -> Self {
44+
let temp: std::mem::MaybeUninit<$ll_name> = std::mem::MaybeUninit::uninit();
45+
$name {
46+
inner: unsafe { Box::<$ll_name>::new(temp.assume_init()) },
47+
}
48+
}
49+
50+
fn as_ptr(&self) -> *const $ll_name {
51+
&*self.inner
52+
}
53+
54+
fn as_mut_ptr(&mut self) -> *mut $ll_name {
55+
&mut *self.inner
56+
}
57+
}
58+
};
59+
}
60+
3361
#[cfg(test)]
3462
mod test {
3563
use crate::error::TskitRustError;

src/ffi.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//! Define traits related to wrapping tskit stuff
2+
3+
/// Define what it means to wrap a tskit struct.
4+
/// The implementation of Drop should call the
5+
/// tsk_foo_free() function corresponding
6+
/// to tsk_foo_t.
7+
pub trait TskitType<T>: Drop {
8+
/// Encapsulate tsk_foo_t and return rust
9+
/// object. Best practices seem to
10+
/// suggest using Box for this.
11+
fn wrap() -> Self;
12+
/// Return const pointer
13+
fn as_ptr(&self) -> *const T;
14+
/// Return mutable pointer
15+
fn as_mut_ptr(&mut self) -> *mut T;
16+
}
17+
18+
#[cfg(test)]
19+
mod tests {
20+
use super::*;
21+
use crate::bindings as ll_bindings;
22+
use ll_bindings::tsk_table_collection_free;
23+
24+
pub struct TableCollectionMock {
25+
inner: Box<ll_bindings::tsk_table_collection_t>,
26+
}
27+
28+
build_tskit_type!(
29+
TableCollectionMock,
30+
ll_bindings::tsk_table_collection_t,
31+
tsk_table_collection_free
32+
);
33+
34+
impl TableCollectionMock {
35+
fn new(len: f64) -> Self {
36+
let mut s = Self::wrap();
37+
38+
let rv = unsafe { ll_bindings::tsk_table_collection_init(s.as_mut_ptr(), 0) };
39+
assert_eq!(rv, 0);
40+
41+
s.inner.sequence_length = len;
42+
43+
s
44+
}
45+
46+
fn sequence_length(&self) -> f64 {
47+
unsafe { (*self.as_ptr()).sequence_length }
48+
}
49+
}
50+
51+
#[test]
52+
fn test_create_mock_type() {
53+
let t = TableCollectionMock::new(10.);
54+
assert_eq!(t.sequence_length() as i64, 10);
55+
}
56+
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod bindings;
99
mod _macros; // Starts w/_ to be sorted at front by rustfmt!
1010
mod edge_table;
1111
pub mod error;
12+
pub mod ffi;
1213
mod mutation_table;
1314
mod node_table;
1415
mod population_table;
@@ -53,4 +54,3 @@ pub fn version() -> &'static str {
5354

5455
// Testing modules
5556
mod test_tsk_variables;
56-

0 commit comments

Comments
 (0)