Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use traits to constrain design of TskBox #573

Merged
merged 1 commit into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/sys/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![macro_use]

macro_rules! impl_tskteardown {
($tsk: ty, $teardown: expr) => {
impl super::TskTeardown for $tsk {
unsafe fn teardown(&mut self) -> i32 {
$teardown(self as _)
}
}
};
}
7 changes: 6 additions & 1 deletion src/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use thiserror::Error;

mod macros;

#[allow(dead_code)]
#[allow(deref_nullptr)]
#[allow(rustdoc::broken_intra_doc_links)]
Expand All @@ -8,8 +10,11 @@ pub mod bindings;
pub mod flags;
mod table_collection;
mod tables;
mod trait_impls;
mod traits;
mod tree;
mod treeseq;
mod tskbox;

// tskit defines this via a type cast
// in a macro. bindgen thus misses it.
Expand All @@ -22,7 +27,7 @@ pub use tables::*;
pub use tree::LLTree;
pub use treeseq::LLTreeSeq;

mod tskbox;
use traits::TskTeardown;

#[non_exhaustive]
#[derive(Error, Debug)]
Expand Down
12 changes: 5 additions & 7 deletions src/sys/table_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use super::bindings::tsk_population_table_t;
#[cfg(feature = "provenance")]
use super::bindings::tsk_provenance_table_t;
use super::bindings::tsk_site_table_t;
use super::bindings::tsk_table_collection_free;
use super::bindings::tsk_table_collection_init;
use super::bindings::tsk_table_collection_t;
use super::tskbox::TskBox;
Expand All @@ -17,10 +16,9 @@ pub struct TableCollection(TskBox<tsk_table_collection_t>);

impl TableCollection {
pub fn new(sequence_length: f64) -> Result<Self, Error> {
let mut tsk = TskBox::new(
|tc: *mut tsk_table_collection_t| unsafe { tsk_table_collection_init(tc, 0) },
tsk_table_collection_free,
)?;
let mut tsk = TskBox::new(|tc: *mut tsk_table_collection_t| unsafe {
tsk_table_collection_init(tc, 0)
})?;
tsk.as_mut().sequence_length = sequence_length;
Ok(Self(tsk))
}
Expand All @@ -30,14 +28,14 @@ impl TableCollection {
// The returned value is uninitialized.
// Using the object prior to initilization is likely to trigger UB.
pub unsafe fn new_uninit() -> Self {
let tsk = unsafe { TskBox::new_uninit(tsk_table_collection_free) };
let tsk = unsafe { TskBox::new_uninit() };
Self(tsk)
}

pub fn copy(&self) -> (i32, TableCollection) {
// SAFETY: the C API requires that the destiniation of a copy be uninitalized.
// Copying into it will initialize the object.
let mut dest = unsafe { TskBox::new_uninit(tsk_table_collection_free) };
let mut dest = unsafe { TskBox::new_uninit() };
// SAFETY: self.as_ptr() is not null and dest matches the input
// expectations of the C API.
let rv = unsafe {
Expand Down
20 changes: 6 additions & 14 deletions src/sys/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ basic_lltableref_impl!(LLIndividualTableRef, tsk_individual_table_t);
basic_lltableref_impl!(LLProvenanceTableRef, tsk_provenance_table_t);

macro_rules! basic_llowningtable_impl {
($llowningtable: ident, $tsktable: ident, $init: ident, $free: ident, $clear: ident) => {
($llowningtable: ident, $tsktable: ident, $init: ident, $clear: ident) => {
#[repr(transparent)]
#[derive(Debug)]
pub struct $llowningtable(super::tskbox::TskBox<super::bindings::$tsktable>);

impl $llowningtable {
pub fn new() -> Self {
let table = super::tskbox::TskBox::new(
|x: *mut super::bindings::$tsktable| unsafe { super::bindings::$init(x, 0) },
super::bindings::$free,
)
.unwrap();
let table =
super::tskbox::TskBox::new(|x: *mut super::bindings::$tsktable| unsafe {
super::bindings::$init(x, 0)
})
.unwrap();
Self(table)
}

Expand All @@ -76,49 +76,42 @@ basic_llowningtable_impl!(
LLOwningEdgeTable,
tsk_edge_table_t,
tsk_edge_table_init,
tsk_edge_table_free,
tsk_edge_table_clear
);
basic_llowningtable_impl!(
LLOwningNodeTable,
tsk_node_table_t,
tsk_node_table_init,
tsk_node_table_free,
tsk_node_table_clear
);
basic_llowningtable_impl!(
LLOwningSiteTable,
tsk_site_table_t,
tsk_site_table_init,
tsk_site_table_free,
tsk_site_table_clear
);
basic_llowningtable_impl!(
LLOwningMutationTable,
tsk_mutation_table_t,
tsk_mutation_table_init,
tsk_mutation_table_free,
tsk_mutation_table_clear
);
basic_llowningtable_impl!(
LLOwningIndividualTable,
tsk_individual_table_t,
tsk_individual_table_init,
tsk_individual_table_free,
tsk_individual_table_clear
);
basic_llowningtable_impl!(
LLOwningMigrationTable,
tsk_migration_table_t,
tsk_migration_table_init,
tsk_migration_table_free,
tsk_migration_table_clear
);
basic_llowningtable_impl!(
LLOwningPopulationTable,
tsk_population_table_t,
tsk_population_table_init,
tsk_population_table_free,
tsk_population_table_clear
);

Expand All @@ -127,6 +120,5 @@ basic_llowningtable_impl!(
LLOwningProvenanceTable,
tsk_provenance_table_t,
tsk_provenance_table_init,
tsk_provenance_table_free,
tsk_provenance_table_clear
);
38 changes: 38 additions & 0 deletions src/sys/trait_impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
impl_tskteardown!(
super::bindings::tsk_table_collection_t,
super::bindings::tsk_table_collection_free
);
impl_tskteardown!(super::bindings::tsk_tree_t, super::bindings::tsk_tree_free);

impl_tskteardown!(
super::bindings::tsk_edge_table_t,
super::bindings::tsk_edge_table_free
);
impl_tskteardown!(
super::bindings::tsk_node_table_t,
super::bindings::tsk_node_table_free
);
impl_tskteardown!(
super::bindings::tsk_site_table_t,
super::bindings::tsk_site_table_free
);
impl_tskteardown!(
super::bindings::tsk_mutation_table_t,
super::bindings::tsk_mutation_table_free
);
impl_tskteardown!(
super::bindings::tsk_individual_table_t,
super::bindings::tsk_individual_table_free
);
impl_tskteardown!(
super::bindings::tsk_population_table_t,
super::bindings::tsk_population_table_free
);
impl_tskteardown!(
super::bindings::tsk_provenance_table_t,
super::bindings::tsk_provenance_table_free
);
impl_tskteardown!(
super::bindings::tsk_migration_table_t,
super::bindings::tsk_migration_table_free
);
13 changes: 13 additions & 0 deletions src/sys/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/// For a type `tsk_foo_t`, this trait abstracts
/// out the functionality of `tsk_foo_free`
///
/// # Note
///
/// This trait should NEVER be part of the public API.
pub trait TskTeardown {
/// # Safety
///
/// Implementations must abide by the expectations
/// of `tsk_foo_free` and C's `free`.
unsafe fn teardown(&mut self) -> i32;
}
9 changes: 3 additions & 6 deletions src/sys/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ pub struct LLTree<'treeseq> {

impl<'treeseq> LLTree<'treeseq> {
pub fn new(treeseq: &'treeseq LLTreeSeq, flags: TreeFlags) -> Result<Self, Error> {
let mut inner = TskBox::new(
|x: *mut super::bindings::tsk_tree_t| unsafe {
super::bindings::tsk_tree_init(x, treeseq.as_ref(), flags.bits())
},
super::bindings::tsk_tree_free,
)?;
let mut inner = TskBox::new(|x: *mut super::bindings::tsk_tree_t| unsafe {
super::bindings::tsk_tree_init(x, treeseq.as_ref(), flags.bits())
})?;
// Gotta ask Jerome about this one--why isn't this handled in tsk_tree_init??
if !flags.contains(TreeFlags::NO_SAMPLE_COUNTS) {
// SAFETY: nobody is null here.
Expand Down
Loading
Loading