diff --git a/src/flags.rs b/src/flags.rs index 5b0ceb785..453a0d022 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -147,3 +147,27 @@ bitflags! { const BUILD_INDEXES = ll_bindings::TSK_BUILD_INDEXES; } } + +bitflags! { + #[derive(Default)] + pub struct TableIntegrityCheckFlags: tsk_flags_t { + /// Default behavior is a set of basic checks + const DEFAULT = 0; + /// Check that edges are ordered + const CHECK_EDGE_ORDERING =ll_bindings::TSK_CHECK_EDGE_ORDERING; + /// Check that sites are ordered + const CHECK_SITE_ORDERING =ll_bindings::TSK_CHECK_SITE_ORDERING; + /// Check for duplicated sites + const CHECK_SITE_DUPLICATES=ll_bindings::TSK_CHECK_SITE_DUPLICATES; + /// Check that mutations are ordered + const CHECK_MUTATION_ORDERING =ll_bindings::TSK_CHECK_MUTATION_ORDERING; + /// Check that individuals are ordered + const CHECK_INDIVIDUAL_ORDERING=ll_bindings::TSK_CHECK_INDIVIDUAL_ORDERING; + /// Check that migrations are ordered + const CHECK_MIGRATION_ORDERING= ll_bindings::TSK_CHECK_MIGRATION_ORDERING; + /// Check that table indexes are valid + const CHECK_INDEXES=ll_bindings::TSK_CHECK_INDEXES; + /// Check tree integrity. Enables most or all of the preceding options. + const CHECK_TREES=ll_bindings::TSK_CHECK_TREES; + } +} diff --git a/src/table_collection.rs b/src/table_collection.rs index c7eca4fdb..e9452a21f 100644 --- a/src/table_collection.rs +++ b/src/table_collection.rs @@ -14,6 +14,7 @@ use crate::SiteTable; use crate::TableAccess; use crate::TableClearOptions; use crate::TableEqualityOptions; +use crate::TableIntegrityCheckFlags; use crate::TableOutputOptions; use crate::TableSortOptions; use crate::TreeSequenceFlags; @@ -686,6 +687,56 @@ impl TableCollection { } ) } + + /// Validate the contents of the table collection + /// + /// # Parameters + /// + /// `flags` is an instance of [`TableIntegrityCheckFlags`] + /// + /// # Return value + /// + /// `0` upon success, or an error code. + /// However, if `flags` contains [`TableIntegrityCheckFlags::CHECK_TREES`], + /// and no error is returned, then the return value is the number + /// of trees. + /// + /// # Note + /// + /// Creating a [`crate::TreeSequence`] from a table collection will automatically + /// run an integrity check. + /// See [`TableCollection::tree_sequence`]. + /// + /// # Examples + /// + /// There are many ways for a table colletion to be invalid. + /// These examples are just the tip of the iceberg. + /// + /// ```should_panic + /// let mut tables = tskit::TableCollection::new(10.0).unwrap(); + /// // Right position is > sequence_length + /// tables.add_edge(0.0, 11.0, 0, 0); + /// tables.check_integrity(tskit::TableIntegrityCheckFlags::default()).unwrap(); + /// ``` + /// + /// ```should_panic + /// let mut tables = tskit::TableCollection::new(10.0).unwrap(); + /// // Left position is < 0.0 + /// tables.add_edge(-1., 10.0, 0, 0); + /// tables.check_integrity(tskit::TableIntegrityCheckFlags::default()).unwrap(); + /// ``` + /// + /// ```should_panic + /// let mut tables = tskit::TableCollection::new(10.0).unwrap(); + /// // Edges cannot have null node ids + /// tables.add_edge(0., 10.0, tskit::NodeId::NULL, 0); + /// tables.check_integrity(tskit::TableIntegrityCheckFlags::default()).unwrap(); + /// ``` + pub fn check_integrity(&self, flags: TableIntegrityCheckFlags) -> TskReturnValue { + let rv = + unsafe { ll_bindings::tsk_table_collection_check_integrity(self.inner, flags.bits()) }; + handle_tsk_return_value!(rv) + } } impl TableAccess for TableCollection {