From def1b686ac86bc8f2b651659c63be9dab03e7906 Mon Sep 17 00:00:00 2001 From: molpopogen Date: Tue, 7 Dec 2021 09:22:20 -0800 Subject: [PATCH] Replace Box with malloc'd raw pointer for tskit types. Closes #179 --- src/_macros.rs | 16 ++-- src/ffi.rs | 8 +- src/table_collection.rs | 102 ++++++++++++-------------- src/trees.rs | 158 ++++++++++++++++++++-------------------- 4 files changed, 141 insertions(+), 143 deletions(-) diff --git a/src/_macros.rs b/src/_macros.rs index 169e5d95b..6f5f33067 100644 --- a/src/_macros.rs +++ b/src/_macros.rs @@ -129,6 +129,10 @@ macro_rules! drop_for_tskit_type { fn drop(&mut self) { let rv = unsafe { $drop(&mut *self.inner) }; panic_on_tskit_error!(rv); + unsafe { + libc::free(self.inner as *mut libc::c_void); + } + self.inner = std::ptr::null_mut(); } } }; @@ -138,11 +142,11 @@ macro_rules! tskit_type_access { ($name: ident, $ll_name: ty) => { impl $crate::TskitTypeAccess<$ll_name> for $name { fn as_ptr(&self) -> *const $ll_name { - &*self.inner + self.inner } fn as_mut_ptr(&mut self) -> *mut $ll_name { - &mut *self.inner + self.inner } } }; @@ -152,10 +156,12 @@ macro_rules! build_tskit_type { ($name: ident, $ll_name: ty, $drop: ident) => { impl $crate::ffi::WrapTskitType<$ll_name> for $name { fn wrap() -> Self { - let temp: std::mem::MaybeUninit<$ll_name> = std::mem::MaybeUninit::uninit(); - $name { - inner: unsafe { Box::<$ll_name>::new(temp.assume_init()) }, + let temp = + unsafe { libc::malloc(std::mem::size_of::<$ll_name>()) as *mut $ll_name }; + if temp.is_null() { + panic!("out of memory"); } + $name { inner: temp } } } drop_for_tskit_type!($name, $drop); diff --git a/src/ffi.rs b/src/ffi.rs index 48d3e5d8b..e2a9b3634 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -25,7 +25,7 @@ mod tests { use ll_bindings::tsk_table_collection_free; pub struct TableCollectionMock { - inner: Box, + inner: *mut ll_bindings::tsk_table_collection_t, } build_tskit_type!( @@ -41,13 +41,15 @@ mod tests { let rv = unsafe { ll_bindings::tsk_table_collection_init(s.as_mut_ptr(), 0) }; assert_eq!(rv, 0); - s.inner.sequence_length = len; + unsafe { + (*s.inner).sequence_length = len; + } s } fn sequence_length(&self) -> f64 { - unsafe { (*self.as_ptr()).sequence_length } + unsafe { (*self.inner).sequence_length } } } diff --git a/src/table_collection.rs b/src/table_collection.rs index daa4efa99..c7eca4fdb 100644 --- a/src/table_collection.rs +++ b/src/table_collection.rs @@ -113,7 +113,7 @@ use ll_bindings::tsk_table_collection_free; /// those needed for current goals in ongoing projects. /// 2. Strengthen some of the error handling. pub struct TableCollection { - inner: Box, + pub(crate) inner: *mut ll_bindings::tsk_table_collection_t, } build_tskit_type!( @@ -132,11 +132,13 @@ impl TableCollection { }); } let mut tables = Self::wrap(); - let rv = unsafe { ll_bindings::tsk_table_collection_init(tables.as_mut_ptr(), 0) }; + let rv = unsafe { ll_bindings::tsk_table_collection_init(tables.inner, 0) }; if rv < 0 { return Err(crate::error::TskitError::ErrorCode { code: rv }); } - tables.inner.sequence_length = sequence_length; + unsafe { + (*tables.inner).sequence_length = sequence_length; + } Ok(tables) } @@ -148,12 +150,12 @@ impl TableCollection { Err(e) => return Err(e), } - let mut tables = tables.unwrap(); + let tables = tables.unwrap(); let c_str = std::ffi::CString::new(filename).unwrap(); let rv = unsafe { ll_bindings::tsk_table_collection_load( - tables.as_mut_ptr(), + tables.inner, c_str.as_ptr(), ll_bindings::TSK_NO_INIT, ) @@ -164,7 +166,7 @@ impl TableCollection { /// Length of the sequence/"genome". pub fn sequence_length(&self) -> f64 { - unsafe { (*self.as_ptr()).sequence_length } + unsafe { (*self.inner).sequence_length } } /// Add a row to the edge table @@ -177,7 +179,7 @@ impl TableCollection { ) -> Result { let rv = unsafe { ll_bindings::tsk_edge_table_add_row( - &mut (*self.as_mut_ptr()).edges, + &mut (*self.inner).edges, left, right, parent.into().0, @@ -202,7 +204,7 @@ impl TableCollection { let md = EncodedMetadata::new(metadata)?; let rv = unsafe { ll_bindings::tsk_edge_table_add_row( - &mut (*self.as_mut_ptr()).edges, + &mut (*self.inner).edges, left, right, parent.into().0, @@ -224,7 +226,7 @@ impl TableCollection { ) -> Result { let rv = unsafe { ll_bindings::tsk_individual_table_add_row( - &mut (*self.as_mut_ptr()).individuals, + &mut (*self.inner).individuals, flags, location.as_ptr(), location.len() as tsk_size_t, @@ -248,7 +250,7 @@ impl TableCollection { let md = EncodedMetadata::new(metadata)?; let rv = unsafe { ll_bindings::tsk_individual_table_add_row( - &mut (*self.as_mut_ptr()).individuals, + &mut (*self.inner).individuals, flags, location.as_ptr(), location.len() as tsk_size_t, @@ -276,7 +278,7 @@ impl TableCollection { ) -> Result { let rv = unsafe { ll_bindings::tsk_migration_table_add_row( - &mut (*self.as_mut_ptr()).migrations, + &mut (*self.inner).migrations, span.0, span.1, node.into().0, @@ -312,7 +314,7 @@ impl TableCollection { let md = EncodedMetadata::new(metadata)?; let rv = unsafe { ll_bindings::tsk_migration_table_add_row( - &mut (*self.as_mut_ptr()).migrations, + &mut (*self.inner).migrations, span.0, span.1, node.into().0, @@ -336,7 +338,7 @@ impl TableCollection { ) -> Result { let rv = unsafe { ll_bindings::tsk_node_table_add_row( - &mut (*self.as_mut_ptr()).nodes, + &mut (*self.inner).nodes, flags, time, population.into().0, @@ -365,7 +367,7 @@ impl TableCollection { let md = EncodedMetadata::new(metadata)?; let rv = unsafe { ll_bindings::tsk_node_table_add_row( - &mut (*self.as_mut_ptr()).nodes, + &mut (*self.inner).nodes, flags, time, population.into().0, @@ -388,7 +390,7 @@ impl TableCollection { let rv = unsafe { ll_bindings::tsk_site_table_add_row( - &mut (*self.as_mut_ptr()).sites, + &mut (*self.inner).sites, position, astate.0, astate.1, @@ -412,7 +414,7 @@ impl TableCollection { let rv = unsafe { ll_bindings::tsk_site_table_add_row( - &mut (*self.as_mut_ptr()).sites, + &mut (*self.inner).sites, position, astate.0, astate.1, @@ -436,7 +438,7 @@ impl TableCollection { let dstate = process_state_input!(derived_state); let rv = unsafe { ll_bindings::tsk_mutation_table_add_row( - &mut (*self.as_mut_ptr()).mutations, + &mut (*self.inner).mutations, site.into().0, node.into().0, parent.into().0, @@ -470,7 +472,7 @@ impl TableCollection { let rv = unsafe { ll_bindings::tsk_mutation_table_add_row( - &mut (*self.as_mut_ptr()).mutations, + &mut (*self.inner).mutations, site.into().0, node.into().0, parent.into().0, @@ -488,7 +490,7 @@ impl TableCollection { pub fn add_population(&mut self) -> Result { let rv = unsafe { ll_bindings::tsk_population_table_add_row( - &mut (*self.as_mut_ptr()).populations, + &mut (*self.inner).populations, std::ptr::null(), 0, ) @@ -505,7 +507,7 @@ impl TableCollection { let md = EncodedMetadata::new(metadata)?; let rv = unsafe { ll_bindings::tsk_population_table_add_row( - &mut (*self.as_mut_ptr()).populations, + &mut (*self.inner).populations, md.as_ptr(), md.len(), ) @@ -523,7 +525,7 @@ impl TableCollection { /// that is currently unused. A future release may break `API` /// here if the `C` library is updated to use flags. pub fn build_index(&mut self) -> TskReturnValue { - let rv = unsafe { ll_bindings::tsk_table_collection_build_index(self.as_mut_ptr(), 0) }; + let rv = unsafe { ll_bindings::tsk_table_collection_build_index(self.inner, 0) }; handle_tsk_return_value!(rv) } @@ -539,8 +541,8 @@ impl TableCollection { if self.is_indexed() { Some(unsafe { std::slice::from_raw_parts( - (*self.as_ptr()).indexes.edge_insertion_order as *const EdgeId, - (*self.as_ptr()).indexes.num_edges as usize, + (*self.inner).indexes.edge_insertion_order as *const EdgeId, + (*self.inner).indexes.num_edges as usize, ) }) } else { @@ -555,8 +557,8 @@ impl TableCollection { if self.is_indexed() { Some(unsafe { std::slice::from_raw_parts( - (*self.as_ptr()).indexes.edge_removal_order as *const EdgeId, - (*self.as_ptr()).indexes.num_edges as usize, + (*self.inner).indexes.edge_removal_order as *const EdgeId, + (*self.inner).indexes.num_edges as usize, ) }) } else { @@ -569,11 +571,7 @@ impl TableCollection { /// be used to affect where sorting starts from for each table. pub fn sort(&mut self, start: &Bookmark, options: TableSortOptions) -> TskReturnValue { let rv = unsafe { - ll_bindings::tsk_table_collection_sort( - self.as_mut_ptr(), - &start.offsets, - options.bits(), - ) + ll_bindings::tsk_table_collection_sort(self.inner, &start.offsets, options.bits()) }; handle_tsk_return_value!(rv) @@ -592,7 +590,7 @@ impl TableCollection { let c_str = std::ffi::CString::new(filename).unwrap(); let rv = unsafe { ll_bindings::tsk_table_collection_dump( - self.as_ptr() as *mut ll_bindings::tsk_table_collection_t, + self.inner as *mut ll_bindings::tsk_table_collection_t, c_str.as_ptr(), options.bits(), ) @@ -606,8 +604,7 @@ impl TableCollection { /// Memory will be released when the object goes out /// of scope. pub fn clear(&mut self, options: TableClearOptions) -> TskReturnValue { - let rv = - unsafe { ll_bindings::tsk_table_collection_clear(self.as_mut_ptr(), options.bits()) }; + let rv = unsafe { ll_bindings::tsk_table_collection_clear(self.inner, options.bits()) }; handle_tsk_return_value!(rv) } @@ -616,7 +613,7 @@ impl TableCollection { /// Not public b/c not very safe. #[allow(dead_code)] fn free(&mut self) -> TskReturnValue { - let rv = unsafe { ll_bindings::tsk_table_collection_free(self.as_mut_ptr()) }; + let rv = unsafe { ll_bindings::tsk_table_collection_free(self.inner) }; handle_tsk_return_value!(rv) } @@ -624,17 +621,14 @@ impl TableCollection { /// Return ``true`` if ``self`` contains the same /// data as ``other``, and ``false`` otherwise. pub fn equals(&self, other: &TableCollection, options: TableEqualityOptions) -> bool { - unsafe { - ll_bindings::tsk_table_collection_equals(self.as_ptr(), other.as_ptr(), options.bits()) - } + unsafe { ll_bindings::tsk_table_collection_equals(self.inner, other.inner, options.bits()) } } /// Return a "deep" copy of the tables. pub fn deepcopy(&self) -> Result { - let mut copy = TableCollection::new(1.)?; + let copy = TableCollection::new(1.)?; - let rv = - unsafe { ll_bindings::tsk_table_collection_copy(self.as_ptr(), copy.as_mut_ptr(), 0) }; + let rv = unsafe { ll_bindings::tsk_table_collection_copy(self.inner, copy.inner, 0) }; handle_tsk_return_value!(rv, copy) } @@ -674,7 +668,7 @@ impl TableCollection { } let rv = unsafe { ll_bindings::tsk_table_collection_simplify( - self.as_mut_ptr(), + self.inner, samples.as_ptr() as *const tsk_id_t, samples.len() as tsk_size_t, options.bits(), @@ -696,31 +690,31 @@ impl TableCollection { impl TableAccess for TableCollection { fn edges(&self) -> EdgeTable { - EdgeTable::new_from_table(&self.inner.edges) + EdgeTable::new_from_table(unsafe { &(*self.inner).edges }) } fn individuals(&self) -> IndividualTable { - IndividualTable::new_from_table(&self.inner.individuals) + IndividualTable::new_from_table(unsafe { &(*self.inner).individuals }) } fn migrations(&self) -> MigrationTable { - MigrationTable::new_from_table(&self.inner.migrations) + MigrationTable::new_from_table(unsafe { &(*self.inner).migrations }) } fn nodes(&self) -> NodeTable { - NodeTable::new_from_table(&self.inner.nodes) + NodeTable::new_from_table(unsafe { &(*self.inner).nodes }) } fn sites(&self) -> SiteTable { - SiteTable::new_from_table(&self.inner.sites) + SiteTable::new_from_table(unsafe { &(*self.inner).sites }) } fn mutations(&self) -> MutationTable { - MutationTable::new_from_table(&self.inner.mutations) + MutationTable::new_from_table(unsafe { &(*self.inner).mutations }) } fn populations(&self) -> PopulationTable { - PopulationTable::new_from_table(&self.inner.populations) + PopulationTable::new_from_table(unsafe { &(*self.inner).populations }) } } @@ -732,7 +726,7 @@ impl crate::provenance::Provenance for TableCollection { let timestamp = humantime::format_rfc3339(std::time::SystemTime::now()).to_string(); let rv = unsafe { ll_bindings::tsk_provenance_table_add_row( - &mut (*self.as_mut_ptr()).provenances, + &mut (*self.inner).provenances, timestamp.as_ptr() as *mut i8, timestamp.len() as tsk_size_t, record.as_ptr() as *mut i8, @@ -743,7 +737,7 @@ impl crate::provenance::Provenance for TableCollection { } fn provenances(&self) -> crate::provenance::ProvenanceTable { - crate::provenance::ProvenanceTable::new_from_table(&self.inner.provenances) + crate::provenance::ProvenanceTable::new_from_table(unsafe { &(*self.inner).provenances }) } } @@ -902,8 +896,8 @@ mod test { // should probably test against what C thinks is going on :) let input = unsafe { std::slice::from_raw_parts( - (*tables.as_ptr()).indexes.edge_insertion_order, - (*tables.as_ptr()).indexes.num_edges as usize, + (*tables.inner).indexes.edge_insertion_order, + (*tables.inner).indexes.num_edges as usize, ) }; @@ -919,8 +913,8 @@ mod test { let output = unsafe { std::slice::from_raw_parts( - (*tables.as_ptr()).indexes.edge_removal_order, - (*tables.as_ptr()).indexes.num_edges as usize, + (*tables.inner).indexes.edge_removal_order, + (*tables.inner).indexes.num_edges as usize, ) }; assert!(!output.is_empty()); diff --git a/src/trees.rs b/src/trees.rs index e9eba789e..a62f6b651 100644 --- a/src/trees.rs +++ b/src/trees.rs @@ -23,7 +23,7 @@ use ll_bindings::{tsk_tree_free, tsk_treeseq_free}; /// /// Wrapper around `tsk_tree_t`. pub struct Tree { - inner: Box, + pub(crate) inner: *mut ll_bindings::tsk_tree_t, current_tree: i32, advanced: bool, num_nodes: tsk_size_t, @@ -41,9 +41,15 @@ tskit_type_access!(Tree, ll_bindings::tsk_tree_t); impl Tree { fn wrap(num_nodes: tsk_size_t, flags: TreeFlags) -> Self { - let temp: std::mem::MaybeUninit = std::mem::MaybeUninit::uninit(); + let temp = unsafe { + libc::malloc(std::mem::size_of::()) + as *mut ll_bindings::tsk_tree_t + }; + if temp.is_null() { + panic!("out of memory"); + } Self { - inner: unsafe { Box::::new(temp.assume_init()) }, + inner: temp, current_tree: 0, advanced: false, num_nodes, @@ -52,9 +58,8 @@ impl Tree { } fn new(ts: &TreeSequence, flags: TreeFlags) -> Result { - let mut tree = Self::wrap(unsafe { (*(*ts.inner).tables).nodes.num_rows }, flags); - let mut rv = - unsafe { ll_bindings::tsk_tree_init(tree.as_mut_ptr(), ts.as_ptr(), flags.bits()) }; + let tree = Self::wrap(unsafe { (*(*ts.inner).tables).nodes.num_rows }, flags); + let mut rv = unsafe { ll_bindings::tsk_tree_init(tree.inner, ts.inner, flags.bits()) }; if rv < 0 { return Err(TskitError::ErrorCode { code: rv }); } @@ -62,9 +67,9 @@ impl Tree { if !flags.contains(TreeFlags::NO_SAMPLE_COUNTS) { rv = unsafe { ll_bindings::tsk_tree_set_tracked_samples( - tree.as_mut_ptr(), + tree.inner, ts.num_samples() as u64, - tree.inner.samples, + (*tree.inner).samples, ) }; } @@ -89,7 +94,7 @@ impl Tree { /// } /// ``` pub fn parent_array(&self) -> &[NodeId] { - tree_array_slice!(self, parent, self.inner.num_nodes) + tree_array_slice!(self, parent, (*self.inner).num_nodes) } /// # Failing examples @@ -124,7 +129,7 @@ impl Tree { /// ``` pub fn samples_array(&self) -> Result<&[NodeId], TskitError> { let num_samples = - unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.as_ptr()).tree_sequence) }; + unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.inner).tree_sequence) }; err_if_not_tracking_samples!(self.flags, tree_array_slice!(self, samples, num_samples)) } @@ -161,7 +166,7 @@ impl Tree { pub fn next_sample_array(&self) -> Result<&[NodeId], TskitError> { err_if_not_tracking_samples!( self.flags, - tree_array_slice!(self, next_sample, self.inner.num_nodes) + tree_array_slice!(self, next_sample, (*self.inner).num_nodes) ) } @@ -198,7 +203,7 @@ impl Tree { pub fn left_sample_array(&self) -> Result<&[NodeId], TskitError> { err_if_not_tracking_samples!( self.flags, - tree_array_slice!(self, left_sample, self.inner.num_nodes) + tree_array_slice!(self, left_sample, (*self.inner).num_nodes) ) } @@ -235,7 +240,7 @@ impl Tree { pub fn right_sample_array(&self) -> Result<&[NodeId], TskitError> { err_if_not_tracking_samples!( self.flags, - tree_array_slice!(self, right_sample, self.inner.num_nodes) + tree_array_slice!(self, right_sample, (*self.inner).num_nodes) ) } @@ -256,7 +261,7 @@ impl Tree { /// } /// ``` pub fn left_sib_array(&self) -> &[NodeId] { - tree_array_slice!(self, left_sib, self.inner.num_nodes) + tree_array_slice!(self, left_sib, (*self.inner).num_nodes) } /// # Failing examples @@ -276,7 +281,7 @@ impl Tree { /// } /// ``` pub fn right_sib_array(&self) -> &[NodeId] { - tree_array_slice!(self, right_sib, self.inner.num_nodes) + tree_array_slice!(self, right_sib, (*self.inner).num_nodes) } /// # Failing examples @@ -296,7 +301,7 @@ impl Tree { /// } /// ``` pub fn left_child_array(&self) -> &[NodeId] { - tree_array_slice!(self, left_child, self.inner.num_nodes) + tree_array_slice!(self, left_child, (*self.inner).num_nodes) } /// # Failing examples @@ -316,13 +321,13 @@ impl Tree { /// } /// ``` pub fn right_child_array(&self) -> &[NodeId] { - tree_array_slice!(self, right_child, self.inner.num_nodes) + tree_array_slice!(self, right_child, (*self.inner).num_nodes) } fn left_sample(&self, u: NodeId) -> Result { err_if_not_tracking_samples!( self.flags, - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.left_sample, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).left_sample, NodeId) .unwrap() ) } @@ -330,19 +335,14 @@ impl Tree { fn right_sample(&self, u: NodeId) -> Result { err_if_not_tracking_samples!( self.flags, - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.right_sample, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).right_sample, NodeId) .unwrap() ) } /// Return the `[left, right)` coordinates of the tree. pub fn interval(&self) -> (f64, f64) { - unsafe { - ( - (*self.as_ptr()).interval.left, - (*self.as_ptr()).interval.right, - ) - } + unsafe { ((*self.inner).interval.left, (*self.inner).interval.right) } } /// Return the length of the genome for which this @@ -358,7 +358,7 @@ impl Tree { /// /// [`TskitError`] if `u` is out of range. pub fn parent(&self, u: NodeId) -> Result { - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.parent, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).parent, NodeId) } /// Get the left child of node `u`. @@ -367,7 +367,7 @@ impl Tree { /// /// [`TskitError`] if `u` is out of range. pub fn left_child(&self, u: NodeId) -> Result { - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.left_child, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).left_child, NodeId) } /// Get the right child of node `u`. @@ -376,7 +376,7 @@ impl Tree { /// /// [`TskitError`] if `u` is out of range. pub fn right_child(&self, u: NodeId) -> Result { - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.right_child, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).right_child, NodeId) } /// Get the left sib of node `u`. @@ -385,7 +385,7 @@ impl Tree { /// /// [`TskitError`] if `u` is out of range. pub fn left_sib(&self, u: NodeId) -> Result { - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.left_sib, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).left_sib, NodeId) } /// Get the right sib of node `u`. @@ -394,7 +394,7 @@ impl Tree { /// /// [`TskitError::IndexError`] if `u` is out of range. pub fn right_sib(&self, u: NodeId) -> Result { - unsafe_tsk_column_access!(u.0, 0, self.num_nodes, self.inner.right_sib, NodeId) + unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).right_sib, NodeId) } /// Obtain the list of samples for the current tree/tree sequence @@ -402,11 +402,11 @@ impl Tree { #[deprecated(since = "0.2.3", note = "Please use Tree::sample_nodes instead")] pub fn samples_to_vec(&self) -> Vec { let num_samples = - unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.as_ptr()).tree_sequence) }; + unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.inner).tree_sequence) }; let mut rv = vec![]; for i in 0..num_samples { - let u = unsafe { *(*(*self.as_ptr()).tree_sequence).samples.offset(i as isize) }; + let u = unsafe { *(*(*self.inner).tree_sequence).samples.offset(i as isize) }; rv.push(u.into()); } rv @@ -415,7 +415,7 @@ impl Tree { /// Get the list of sample nodes as a slice. pub fn sample_nodes(&self) -> &[NodeId] { let num_samples = - unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.as_ptr()).tree_sequence) }; + unsafe { ll_bindings::tsk_treeseq_get_num_samples((*self.inner).tree_sequence) }; tree_array_slice!(self, samples, num_samples) } @@ -506,7 +506,7 @@ impl Tree { /// This is a convenience function for accessing node times, etc.. pub fn node_table<'a>(&'a self) -> crate::NodeTable<'a> { crate::NodeTable::<'a>::new_from_table(unsafe { - &(*(*(*self.as_ptr()).tree_sequence).tables).nodes + &(*(*(*self.inner).tree_sequence).tables).nodes }) } @@ -543,7 +543,7 @@ impl Tree { pub fn num_tracked_samples(&self, u: NodeId) -> Result { let mut n = u64::MAX; let np: *mut u64 = &mut n; - let code = unsafe { ll_bindings::tsk_tree_get_num_tracked_samples(self.as_ptr(), u.0, np) }; + let code = unsafe { ll_bindings::tsk_tree_get_num_tracked_samples(self.inner, u.0, np) }; handle_tsk_return_value!(code, n) } @@ -562,9 +562,8 @@ impl Tree { pub fn kc_distance(&self, other: &Tree, lambda: f64) -> Result { let mut kc = f64::NAN; let kcp: *mut f64 = &mut kc; - let code = unsafe { - ll_bindings::tsk_tree_kc_distance(self.as_ptr(), other.as_ptr(), lambda, kcp) - }; + let code = + unsafe { ll_bindings::tsk_tree_kc_distance(self.inner, other.inner, lambda, kcp) }; handle_tsk_return_value!(code, kc) } } @@ -573,9 +572,9 @@ impl streaming_iterator::StreamingIterator for Tree { type Item = Tree; fn advance(&mut self) { let rv = if self.current_tree == 0 { - unsafe { ll_bindings::tsk_tree_first(self.as_mut_ptr()) } + unsafe { ll_bindings::tsk_tree_first(self.inner) } } else { - unsafe { ll_bindings::tsk_tree_next(self.as_mut_ptr()) } + unsafe { ll_bindings::tsk_tree_next(self.inner) } }; if rv == 0 { self.advanced = false; @@ -599,9 +598,9 @@ impl streaming_iterator::StreamingIterator for Tree { impl streaming_iterator::DoubleEndedStreamingIterator for Tree { fn advance_back(&mut self) { let rv = if self.current_tree == 0 { - unsafe { ll_bindings::tsk_tree_last(self.as_mut_ptr()) } + unsafe { ll_bindings::tsk_tree_last(self.inner) } } else { - unsafe { ll_bindings::tsk_tree_prev(self.as_mut_ptr()) } + unsafe { ll_bindings::tsk_tree_prev(self.inner) } }; if rv == 0 { self.advanced = false; @@ -686,7 +685,7 @@ impl<'a> RootIterator<'a> { fn new(tree: &'a Tree) -> Self { RootIterator { current_root: None, - next_root: unsafe { ll_bindings::tsk_tree_get_left_root(tree.as_ptr()).into() }, + next_root: unsafe { ll_bindings::tsk_tree_get_left_root(tree.inner).into() }, tree, } } @@ -819,17 +818,17 @@ impl NodeIterator for SamplesIterator<'_> { if r == self.last_sample_index { //let cr = Some(self.tree.samples(r).unwrap()); let cr = - Some(unsafe { *(*self.tree.as_ptr()).samples.offset(r.0 as isize) }.into()); + Some(unsafe { *(*self.tree.inner).samples.offset(r.0 as isize) }.into()); self.next_sample_index = NodeId::NULL; cr } else { assert!(r >= 0); //let cr = Some(self.tree.samples(r).unwrap()); let cr = - Some(unsafe { *(*self.tree.as_ptr()).samples.offset(r.0 as isize) }.into()); + Some(unsafe { *(*self.tree.inner).samples.offset(r.0 as isize) }.into()); //self.next_sample_index = self.next_sample[r]; self.next_sample_index = - unsafe { *(*self.tree.as_ptr()).next_sample.offset(r.0 as isize) }.into(); + unsafe { *(*self.tree.inner).next_sample.offset(r.0 as isize) }.into(); cr } } @@ -867,7 +866,7 @@ iterator_for_nodeiterator!(SamplesIterator<'_>); /// let treeseq = tables.tree_sequence(tskit::TreeSequenceFlags::default()).unwrap(); /// ``` pub struct TreeSequence { - inner: Box, + pub(crate) inner: *mut ll_bindings::tsk_treeseq_t, } build_tskit_type!(TreeSequence, ll_bindings::tsk_treeseq_t, tsk_treeseq_free); @@ -910,11 +909,9 @@ impl TreeSequence { /// tskit::TreeSequenceFlags::default()).unwrap(); /// ``` pub fn new(tables: TableCollection, flags: TreeSequenceFlags) -> Result { - let mut t = tables; - let mut treeseq = Self::wrap(); - let rv = unsafe { - ll_bindings::tsk_treeseq_init(treeseq.as_mut_ptr(), t.as_mut_ptr(), flags.bits()) - }; + let t = tables; + let treeseq = Self::wrap(); + let rv = unsafe { ll_bindings::tsk_treeseq_init(treeseq.inner, t.inner, flags.bits()) }; handle_tsk_return_value!(rv, treeseq) } @@ -930,7 +927,7 @@ impl TreeSequence { let c_str = std::ffi::CString::new(filename).unwrap(); let rv = unsafe { ll_bindings::tsk_treeseq_dump( - self.as_ptr() as *mut ll_bindings::tsk_treeseq_t, + self.inner as *mut ll_bindings::tsk_treeseq_t, c_str.as_ptr(), options.bits(), ) @@ -953,11 +950,10 @@ impl TreeSequence { /// /// [`TskitError`] will be raised if the underlying C library returns an error code. pub fn dump_tables(&self) -> Result { - let mut copy = TableCollection::new(1.)?; + let copy = TableCollection::new(1.)?; - let rv = unsafe { - ll_bindings::tsk_table_collection_copy(self.inner.tables, copy.as_mut_ptr(), 0) - }; + let rv = + unsafe { ll_bindings::tsk_table_collection_copy((*self.inner).tables, copy.inner, 0) }; handle_tsk_return_value!(rv, copy) } @@ -1014,11 +1010,11 @@ impl TreeSequence { note = "Please use TreeSequence::sample_nodes instead" )] pub fn samples_to_vec(&self) -> Vec { - let num_samples = unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.as_ptr()) }; + let num_samples = unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.inner) }; let mut rv = vec![]; for i in 0..num_samples { - let u = NodeId::from(unsafe { *(*self.as_ptr()).samples.offset(i as isize) }); + let u = NodeId::from(unsafe { *(*self.inner).samples.offset(i as isize) }); rv.push(u); } rv @@ -1026,13 +1022,13 @@ impl TreeSequence { /// Get the list of sample nodes as a slice. pub fn sample_nodes(&self) -> &[NodeId] { - let num_samples = unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.as_ptr()) }; + let num_samples = unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.inner) }; tree_array_slice!(self, samples, num_samples) } /// Get the number of trees. pub fn num_trees(&self) -> tsk_size_t { - unsafe { ll_bindings::tsk_treeseq_get_num_trees(self.as_ptr()) } + unsafe { ll_bindings::tsk_treeseq_get_num_trees(self.inner) } } /// Calculate the average Kendall-Colijn (`K-C`) distance between @@ -1049,15 +1045,14 @@ impl TreeSequence { pub fn kc_distance(&self, other: &TreeSequence, lambda: f64) -> Result { let mut kc: f64 = f64::NAN; let kcp: *mut f64 = &mut kc; - let code = unsafe { - ll_bindings::tsk_treeseq_kc_distance(self.as_ptr(), other.as_ptr(), lambda, kcp) - }; + let code = + unsafe { ll_bindings::tsk_treeseq_kc_distance(self.inner, other.inner, lambda, kcp) }; handle_tsk_return_value!(code, kc) } // FIXME: document pub fn num_samples(&self) -> tsk_size_t { - unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.as_ptr()) } + unsafe { ll_bindings::tsk_treeseq_get_num_samples(self.inner) } } /// Simplify tables and return a new tree sequence. @@ -1079,20 +1074,21 @@ impl TreeSequence { options: SimplificationOptions, idmap: bool, ) -> Result<(Self, Option>), TskitError> { - let mut tables = TableCollection::new(unsafe { (*self.inner.tables).sequence_length })?; + let mut tables = TableCollection::new(unsafe { (*(*self.inner).tables).sequence_length })?; tables.build_index().unwrap(); - let mut ts = tables.tree_sequence(TreeSequenceFlags::default())?; + let ts = tables.tree_sequence(TreeSequenceFlags::default())?; let mut output_node_map: Vec = vec![]; if idmap { output_node_map.resize(self.nodes().num_rows() as usize, NodeId::NULL); } let rv = unsafe { ll_bindings::tsk_treeseq_simplify( - self.as_ptr(), + self.inner, + // NOTE: casting away const-ness: samples.as_ptr() as *mut tsk_id_t, samples.len() as tsk_size_t, options.bits(), - ts.as_mut_ptr(), + ts.inner, match idmap { true => output_node_map.as_mut_ptr() as *mut tsk_id_t, false => std::ptr::null_mut(), @@ -1114,31 +1110,31 @@ impl TreeSequence { impl TableAccess for TreeSequence { fn edges(&self) -> EdgeTable { - EdgeTable::new_from_table(unsafe { &(*self.inner.tables).edges }) + EdgeTable::new_from_table(unsafe { &(*(*self.inner).tables).edges }) } fn individuals(&self) -> IndividualTable { - IndividualTable::new_from_table(unsafe { &(*self.inner.tables).individuals }) + IndividualTable::new_from_table(unsafe { &(*(*self.inner).tables).individuals }) } fn migrations(&self) -> MigrationTable { - MigrationTable::new_from_table(unsafe { &(*self.inner.tables).migrations }) + MigrationTable::new_from_table(unsafe { &(*(*self.inner).tables).migrations }) } fn nodes(&self) -> NodeTable { - NodeTable::new_from_table(unsafe { &(*self.inner.tables).nodes }) + NodeTable::new_from_table(unsafe { &(*(*self.inner).tables).nodes }) } fn sites(&self) -> SiteTable { - SiteTable::new_from_table(unsafe { &(*self.inner.tables).sites }) + SiteTable::new_from_table(unsafe { &(*(*self.inner).tables).sites }) } fn mutations(&self) -> MutationTable { - MutationTable::new_from_table(unsafe { &(*self.inner.tables).mutations }) + MutationTable::new_from_table(unsafe { &(*(*self.inner).tables).mutations }) } fn populations(&self) -> PopulationTable { - PopulationTable::new_from_table(unsafe { &(*self.inner.tables).populations }) + PopulationTable::new_from_table(unsafe { &(*(*self.inner).tables).populations }) } } @@ -1150,7 +1146,7 @@ impl crate::provenance::Provenance for TreeSequence { let timestamp = humantime::format_rfc3339(std::time::SystemTime::now()).to_string(); let rv = unsafe { ll_bindings::tsk_provenance_table_add_row( - &mut (*self.inner.tables).provenances, + &mut (*(*self.inner).tables).provenances, timestamp.as_ptr() as *mut i8, timestamp.len() as tsk_size_t, record.as_ptr() as *mut i8, @@ -1162,7 +1158,7 @@ impl crate::provenance::Provenance for TreeSequence { fn provenances(&self) -> crate::provenance::ProvenanceTable { crate::provenance::ProvenanceTable::new_from_table(unsafe { - &(*self.inner.tables).provenances + &(*(*self.inner).tables).provenances }) } } @@ -1258,7 +1254,7 @@ pub(crate) mod test_trees { #[test] fn test_num_tracked_samples() { let treeseq = treeseq_from_small_table_collection(); - assert_eq!(treeseq.inner.num_samples, 2); + assert_eq!(treeseq.num_samples(), 2); let mut tree_iter = treeseq.tree_iterator(TreeFlags::default()).unwrap(); if let Some(tree) = tree_iter.next() { assert_eq!(tree.num_tracked_samples(2.into()).unwrap(), 1); @@ -1271,7 +1267,7 @@ pub(crate) mod test_trees { #[test] fn test_num_tracked_samples_not_tracking_samples() { let treeseq = treeseq_from_small_table_collection(); - assert_eq!(treeseq.inner.num_samples, 2); + assert_eq!(treeseq.num_samples(), 2); let mut tree_iter = treeseq.tree_iterator(TreeFlags::NO_SAMPLE_COUNTS).unwrap(); if let Some(tree) = tree_iter.next() { assert_eq!(tree.num_tracked_samples(2.into()).unwrap(), 0); @@ -1321,7 +1317,7 @@ pub(crate) mod test_trees { #[test] fn test_iterate_samples_two_trees() { let treeseq = treeseq_from_small_table_collection_two_trees(); - assert_eq!(treeseq.inner.num_trees, 2); + assert_eq!(treeseq.num_trees(), 2); let mut tree_iter = treeseq.tree_iterator(TreeFlags::SAMPLE_LISTS).unwrap(); while let Some(tree) = tree_iter.next() { for n in tree.traverse_nodes(NodeTraversalOrder::Preorder) {