From ceec9bda7f47f8de6526855741cc02b5aa6c0575 Mon Sep 17 00:00:00 2001 From: "Kevin R. Thornton" Date: Tue, 19 Jul 2022 06:15:51 -0700 Subject: [PATCH] refactor: use macros to implement adding table rows. --- src/_macros.rs | 416 ++++++++++++++++++++++++++++++++++++++-- src/edge_table.rs | 47 +---- src/population_table.rs | 25 +-- src/table_collection.rs | 333 +++----------------------------- 4 files changed, 429 insertions(+), 392 deletions(-) diff --git a/src/_macros.rs b/src/_macros.rs index 54e51a78b..9bc414d18 100644 --- a/src/_macros.rs +++ b/src/_macros.rs @@ -576,6 +576,29 @@ macro_rules! build_owned_tables { }; } +macro_rules! node_table_add_row_details { + ($flags: ident, + $time: ident, + $population: ident, + $individual: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let rv = unsafe { + $crate::bindings::tsk_node_table_add_row( + &mut $table, + $flags.into().bits(), + $time.into().0, + $population.into().0, + $individual.into().0, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + macro_rules! node_table_add_row { ($(#[$attr:meta])* => $name: ident, $self: ident, $table: ident $(, $table2: ident )?) => { $(#[$attr])* @@ -586,19 +609,13 @@ macro_rules! node_table_add_row { population: impl Into<$crate::PopulationId>, individual: impl Into<$crate::IndividualId>, ) -> Result<$crate::NodeId, $crate::TskitError> { - let rv = unsafe { - $crate::bindings::tsk_node_table_add_row( - &mut (*$self.$table)$(.$table2)?, - flags.into().bits(), - time.into().0, - population.into().0, - individual.into().0, - std::ptr::null(), - 0, - ) - }; - - handle_tsk_return_value!(rv, rv.into()) + node_table_add_row_details!(flags, + time, + population, + individual, + std::ptr::null(), + 0, + (*$self.$table)$(.$table2)?) } }; } @@ -618,15 +635,372 @@ macro_rules! node_table_add_row_with_metadata { M: $crate::metadata::NodeMetadata, { let md = $crate::metadata::EncodedMetadata::new(metadata)?; + node_table_add_row_details!(flags, + time, + population, + individual, + md.as_ptr(), + md.len().into(), + (*$self.$table)$(.$table2)?) + } + }; +} + +macro_rules! edge_table_add_row_details { + ($left: ident, + $right: ident, + $parent: ident, + $child: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let rv = unsafe { + $crate::bindings::tsk_edge_table_add_row( + &mut $table, + $left.into().0, + $right.into().0, + $parent.into().0, + $child.into().0, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! edge_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name( + &mut $self, + left: impl Into<$crate::Position>, + right: impl Into<$crate::Position>, + parent: impl Into<$crate::NodeId>, + child: impl Into<$crate::NodeId>, + ) -> Result<$crate::EdgeId, $crate::TskitError> { + edge_table_add_row_details!(left, + right, + parent, + child, + std::ptr::null(), + 0, + $table) + } + }; +} + +macro_rules! edge_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name( + &mut $self, + left: impl Into<$crate::Position>, + right: impl Into<$crate::Position>, + parent: impl Into<$crate::NodeId>, + child: impl Into<$crate::NodeId>, + metadata: &M, + ) -> Result<$crate::EdgeId, $crate::TskitError> + where + M: $crate::metadata::EdgeMetadata { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + edge_table_add_row_details!(left, + right, + parent, + child, + md.as_ptr(), + md.len().into(), + $table) + } + }; +} + +macro_rules! population_table_add_row_details { + ($metadata: expr, $metadata_len: expr, $table: expr) => {{ + let rv = unsafe { + $crate::bindings::tsk_population_table_add_row(&mut $table, $metadata, $metadata_len) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! population_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self) -> Result<$crate::PopulationId, $crate::TskitError> { + population_table_add_row_details!(std::ptr::null(), 0, $table) + } + }; +} + +macro_rules! population_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, metadata: &M) -> Result<$crate::PopulationId, $crate::TskitError> + where M: $crate::metadata::PopulationMetadata { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + population_table_add_row_details!(md.as_ptr(), md.len().into(), $table) + } + }; +} + +macro_rules! individual_table_add_row_details { + ($flags: ident, + $location: ident, + $parents: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let rv = unsafe { + $crate::bindings::tsk_individual_table_add_row( + &mut $table, + $flags.into().bits(), + $location.get_slice().as_ptr().cast::(), + $location.get_slice().len() as $crate::bindings::tsk_size_t, + $parents + .get_slice() + .as_ptr() + .cast::<$crate::bindings::tsk_id_t>(), + $parents.get_slice().len() as $crate::bindings::tsk_size_t, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! individual_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + flags: impl Into<$crate::IndividualFlags>, + location: impl $crate::IndividualLocation, + parents: impl $crate::IndividualParents, + ) -> Result<$crate::IndividualId, $crate::TskitError> { + individual_table_add_row_details!(flags, + location, + parents, + std::ptr::null(), + 0, + $table) + } + }; +} + +macro_rules! individual_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + flags: impl Into<$crate::IndividualFlags>, + location: impl $crate::IndividualLocation, + parents: impl $crate::IndividualParents, + metadata: &M, + ) -> Result<$crate::IndividualId, $crate::TskitError> + where M: $crate::metadata::IndividualMetadata { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + individual_table_add_row_details!(flags, + location, + parents, + md.as_ptr(), + md.len().into(), + $table) + } + }; +} + +macro_rules! mutation_table_add_row_details { + ($site: ident, $node: ident, $parent: ident, + $time: ident, $derived_state: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let dstate = process_state_input!($derived_state); + let rv = unsafe { + $crate::bindings::tsk_mutation_table_add_row( + &mut $table, + $site.into().0, + $node.into().0, + $parent.into().0, + $time.into().0, + dstate.0, + dstate.1, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! mutation_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + site: impl Into<$crate::SiteId>, + node: impl Into<$crate::NodeId>, + parent: impl Into<$crate::MutationId>, + time: impl Into<$crate::Time>, + derived_state: Option<&[u8]>) -> Result<$crate::MutationId, $crate::TskitError> + { + mutation_table_add_row_details!(site, + node, + parent, + time, + derived_state, + std::ptr::null(), + 0, + $table) + } + }; +} + +macro_rules! mutation_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + site: impl Into<$crate::SiteId>, + node: impl Into<$crate::NodeId>, + parent: impl Into<$crate::MutationId>, + time: impl Into<$crate::Time>, + derived_state: Option<&[u8]>, + metadata: &M) -> Result<$crate::MutationId, $crate::TskitError> + where + M: $crate::metadata::MutationMetadata + { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + mutation_table_add_row_details!(site, + node, + parent, + time, + derived_state, + md.as_ptr(), + md.len().into(), + $table) + } + }; +} + +macro_rules! site_table_add_row_details { + ($position: ident, + $ancestral_state: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let astate = process_state_input!($ancestral_state); + let rv = unsafe { + $crate::bindings::tsk_site_table_add_row( + &mut $table, + $position.into().0, + astate.0, + astate.1, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! site_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + position: impl Into<$crate::Position>, + ancestral_state: Option<&[u8]>) -> Result<$crate::SiteId, $crate::TskitError> { + site_table_add_row_details!(position, ancestral_state, + std::ptr::null(), 0, $table) + } + }; +} + +macro_rules! site_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + position: impl Into<$crate::Position>, + ancestral_state: Option<&[u8]>, + metadata: &M) -> Result<$crate::SiteId, $crate::TskitError> + where M: $crate::metadata::SiteMetadata { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + site_table_add_row_details!(position, ancestral_state, + md.as_ptr(), + md.len().into(), + $table) + } + }; +} + +macro_rules! migration_table_add_row_details { + ($span: ident, + $node: ident, + $source_dest: ident, + $time: ident, + $metadata: expr, + $metadata_len: expr, + $table: expr) => {{ + let rv = unsafe { + $crate::bindings::tsk_migration_table_add_row( + &mut $table, + $span.0.into().0, + $span.1.into().0, + $node.into().0, + $source_dest.0.into().0, + $source_dest.1.into().0, + $time.into().0, + $metadata, + $metadata_len, + ) + }; + handle_tsk_return_value!(rv, rv.into()) + }}; +} + +macro_rules! migration_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + span: (impl Into<$crate::Position>, impl Into<$crate::Position>), + node: impl Into<$crate::NodeId>, + source_dest: (impl Into<$crate::PopulationId>, impl Into<$crate::PopulationId>), + time: impl Into<$crate::Time>) + -> Result<$crate::MigrationId, $crate::TskitError> { + migration_table_add_row_details!(span, node, source_dest, time, std::ptr::null(), 0, $table) + } + }; +} + +macro_rules! migration_table_add_row_with_metadata { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, + span: (impl Into<$crate::Position>, impl Into<$crate::Position>), + node: impl Into<$crate::NodeId>, + source_dest: (impl Into<$crate::PopulationId>, impl Into<$crate::PopulationId>), + time: impl Into<$crate::Time>, + metadata: &M) + -> Result<$crate::MigrationId, $crate::TskitError> + where M: $crate::metadata::MigrationMetadata { + let md = $crate::metadata::EncodedMetadata::new(metadata)?; + migration_table_add_row_details!(span, node, source_dest, time, + md.as_ptr(), md.len().into(), $table) + } + }; +} + +#[cfg(any(doc, feature = "provenance"))] +macro_rules! provenance_table_add_row { + ($(#[$attr:meta])* => $name: ident, $self: ident, $table: expr) => { + $(#[$attr])* + pub fn $name(&mut $self, record: &str) -> Result<$crate::ProvenanceId, $crate::TskitError> { + let timestamp = humantime::format_rfc3339(std::time::SystemTime::now()).to_string(); let rv = unsafe { - $crate::bindings::tsk_node_table_add_row( - &mut (*$self.$table)$(.$table2)?, - flags.into().bits(), - time.into().0, - population.into().0, - individual.into().0, - md.as_ptr(), - md.len().into(), + $crate::bindings::tsk_provenance_table_add_row( + &mut $table, + timestamp.as_ptr() as *mut i8, + timestamp.len() as tsk_size_t, + record.as_ptr() as *mut i8, + record.len() as tsk_size_t, ) }; handle_tsk_return_value!(rv, rv.into()) diff --git a/src/edge_table.rs b/src/edge_table.rs index 31ef525a0..e80f79218 100644 --- a/src/edge_table.rs +++ b/src/edge_table.rs @@ -218,51 +218,8 @@ pub struct OwnedEdgeTable { } impl OwnedEdgeTable { - pub fn add_row( - &mut self, - left: impl Into, - right: impl Into, - parent: impl Into, - child: impl Into, - ) -> Result { - let rv = unsafe { - ll_bindings::tsk_edge_table_add_row( - &mut (*self.table), - left.into().0, - right.into().0, - parent.into().0, - child.into().0, - std::ptr::null(), - 0, - ) - }; - - handle_tsk_return_value!(rv, EdgeId::from(rv)) - } - - pub fn add_row_with_metadata( - &mut self, - left: impl Into, - right: impl Into, - parent: impl Into, - child: impl Into, - metadata: &M, - ) -> Result { - let md = crate::metadata::EncodedMetadata::new(metadata)?; - let rv = unsafe { - ll_bindings::tsk_edge_table_add_row( - &mut (*self.table), - left.into().0, - right.into().0, - parent.into().0, - child.into().0, - md.as_ptr(), - md.len().into(), - ) - }; - - handle_tsk_return_value!(rv, EdgeId::from(rv)) - } + edge_table_add_row!(=> add_row, self, *self.table); + edge_table_add_row_with_metadata!(=> add_row_with_metadata, self, *self.table); } build_owned_tables!( diff --git a/src/population_table.rs b/src/population_table.rs index 237d6be3f..935d062ed 100644 --- a/src/population_table.rs +++ b/src/population_table.rs @@ -165,29 +165,8 @@ pub struct OwnedPopulationTable { } impl OwnedPopulationTable { - pub fn add_row(&mut self) -> Result { - let rv = unsafe { - ll_bindings::tsk_population_table_add_row(&mut (*self.table), std::ptr::null(), 0) - }; - - handle_tsk_return_value!(rv, PopulationId::from(rv)) - } - - pub fn add_row_with_metadata( - &mut self, - metadata: &M, - ) -> Result { - let md = crate::metadata::EncodedMetadata::new(metadata)?; - let rv = unsafe { - ll_bindings::tsk_population_table_add_row( - &mut (*self.table), - md.as_ptr(), - md.len().into(), - ) - }; - - handle_tsk_return_value!(rv, PopulationId::from(rv)) - } + population_table_add_row!(=> add_row, self, *self.table); + population_table_add_row_with_metadata!(=> add_row_with_metadata, self, *self.table); } build_owned_tables!( diff --git a/src/table_collection.rs b/src/table_collection.rs index 4d308a6a6..1a1d32afb 100644 --- a/src/table_collection.rs +++ b/src/table_collection.rs @@ -1,12 +1,8 @@ use crate::bindings as ll_bindings; use crate::error::TskitError; use crate::ffi::WrapTskitType; -use crate::metadata::*; -use crate::traits::IndividualLocation; -use crate::traits::IndividualParents; use crate::types::Bookmark; use crate::EdgeTable; -use crate::IndividualFlags; use crate::IndividualTable; use crate::IndividualTableSortOptions; use crate::MigrationTable; @@ -22,12 +18,11 @@ use crate::TableEqualityOptions; use crate::TableIntegrityCheckFlags; use crate::TableOutputOptions; use crate::TableSortOptions; -use crate::Time; use crate::TreeSequenceFlags; use crate::TskReturnValue; use crate::TskitTypeAccess; use crate::{tsk_id_t, tsk_size_t}; -use crate::{EdgeId, IndividualId, MigrationId, MutationId, NodeId, PopulationId, SiteId}; +use crate::{EdgeId, NodeId}; use ll_bindings::tsk_table_collection_free; use mbox::MBox; @@ -184,6 +179,7 @@ impl TableCollection { unsafe { (*self.as_ptr()).sequence_length }.into() } + edge_table_add_row!( /// Add a row to the edge table /// /// # Examples @@ -226,28 +222,9 @@ impl TableCollection { /// /// See [`TableCollection::check_integrity`] for how to catch these data model /// violations. - pub fn add_edge, R: Into, P: Into, C: Into>( - &mut self, - left: L, - right: R, - parent: P, - child: C, - ) -> Result { - let rv = unsafe { - ll_bindings::tsk_edge_table_add_row( - &mut (*self.as_mut_ptr()).edges, - left.into().0, - right.into().0, - parent.into().0, - child.into().0, - std::ptr::null(), - 0, - ) - }; - - handle_tsk_return_value!(rv, EdgeId::from(rv)) - } + => add_edge, self, (*self.inner).edges); + edge_table_add_row_with_metadata!( /// Add a row with optional metadata to the edge table /// /// # Examples @@ -268,36 +245,9 @@ impl TableCollection { /// assert!(tables.add_edge_with_metadata(0., 53., 1, 11, &metadata).is_ok()); /// # } /// ``` - pub fn add_edge_with_metadata< - L: Into, - R: Into, - P: Into, - C: Into, - M: EdgeMetadata, - >( - &mut self, - left: L, - right: R, - parent: P, - child: C, - metadata: &M, - ) -> Result { - let md = EncodedMetadata::new(metadata)?; - let rv = unsafe { - ll_bindings::tsk_edge_table_add_row( - &mut (*self.as_mut_ptr()).edges, - left.into().0, - right.into().0, - parent.into().0, - child.into().0, - md.as_ptr(), - md.len().into(), - ) - }; - - handle_tsk_return_value!(rv, EdgeId::from(rv)) - } + => add_edge_with_metadata, self, (*self.inner).edges); + individual_table_add_row!( /// Add a row to the individual table /// /// # Examples @@ -334,28 +284,9 @@ impl TableCollection { /// # None => panic!("expected parents"), /// # } /// ``` - /// - pub fn add_individual, L: IndividualLocation, I: IndividualParents>( - &mut self, - flags: F, - location: L, - parents: I, - ) -> Result { - let rv = unsafe { - ll_bindings::tsk_individual_table_add_row( - &mut (*self.as_mut_ptr()).individuals, - flags.into().bits(), - location.get_slice().as_ptr().cast::(), - location.get_slice().len() as tsk_size_t, - parents.get_slice().as_ptr().cast::(), - parents.get_slice().len() as tsk_size_t, - std::ptr::null(), - 0, - ) - }; - handle_tsk_return_value!(rv, IndividualId::from(rv)) - } + => add_individual, self, (*self.inner).individuals); + individual_table_add_row_with_metadata!( /// Add a row with metadata to the individual table /// /// # Examples @@ -379,34 +310,9 @@ impl TableCollection { /// # let decoded = tables.individuals().metadata::(0.into()).unwrap().unwrap(); /// # assert_eq!(decoded.x, 1); /// # } - pub fn add_individual_with_metadata< - F: Into, - L: IndividualLocation, - I: IndividualParents, - M: IndividualMetadata, - >( - &mut self, - flags: F, - location: L, - parents: I, - metadata: &M, - ) -> Result { - let md = EncodedMetadata::new(metadata)?; - let rv = unsafe { - ll_bindings::tsk_individual_table_add_row( - &mut (*self.as_mut_ptr()).individuals, - flags.into().bits(), - location.get_slice().as_ptr().cast::(), - location.get_slice().len() as tsk_size_t, - parents.get_slice().as_ptr().cast::(), - parents.get_slice().len() as tsk_size_t, - md.as_ptr(), - md.len().into(), - ) - }; - handle_tsk_return_value!(rv, IndividualId::from(rv)) - } + => add_individual_with_metadata, self, (*self.inner).individuals); + migration_table_add_row!( /// Add a row to the migration table /// /// # Warnings @@ -422,36 +328,9 @@ impl TableCollection { /// (0, 1), /// 53.5).is_ok()); /// ``` - pub fn add_migration< - L: Into, - R: Into, - N: Into, - SOURCE: Into, - DEST: Into, - T: Into