diff --git a/examples/forward_simulation.rs b/examples/forward_simulation.rs index 808590429..77b3d8521 100644 --- a/examples/forward_simulation.rs +++ b/examples/forward_simulation.rs @@ -23,7 +23,6 @@ use rand::rngs::StdRng; use rand::Rng; use rand::SeedableRng; use rand_distr::{Exp, Uniform}; -use tskit::TableAccess; use tskit::TskitTypeAccess; #[derive(clap::Parser)] diff --git a/src/_macros.rs b/src/_macros.rs index 9aa5db7a9..1942875cc 100644 --- a/src/_macros.rs +++ b/src/_macros.rs @@ -518,7 +518,7 @@ macro_rules! build_owned_tables { } impl std::ops::Deref for $name { - type Target = $deref<'static>; + type Target = $deref; fn deref(&self) -> &Self::Target { // SAFETY: that T* and &T have same layout, diff --git a/src/edge_table.rs b/src/edge_table.rs index 3fa00af81..b660d24ea 100644 --- a/src/edge_table.rs +++ b/src/edge_table.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use crate::bindings as ll_bindings; use crate::metadata; use crate::Position; @@ -28,7 +30,7 @@ impl PartialEq for EdgeTableRow { } fn make_edge_table_row(table: &EdgeTable, pos: tsk_id_t) -> Option { - let table_ref = table.table_; + let table_ref = table.as_ref(); Some(EdgeTableRow { id: pos.into(), left: table.left(pos)?, @@ -39,8 +41,8 @@ fn make_edge_table_row(table: &EdgeTable, pos: tsk_id_t) -> Option }) } -pub(crate) type EdgeTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a EdgeTable<'a>>; -pub(crate) type EdgeTableIterator<'a> = crate::table_iterator::TableIterator>; +pub(crate) type EdgeTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a EdgeTable>; +pub(crate) type EdgeTableIterator = crate::table_iterator::TableIterator; impl<'a> Iterator for EdgeTableRefIterator<'a> { type Item = EdgeTableRow; @@ -52,7 +54,7 @@ impl<'a> Iterator for EdgeTableRefIterator<'a> { } } -impl<'a> Iterator for EdgeTableIterator<'a> { +impl Iterator for EdgeTableIterator { type Item = EdgeTableRow; fn next(&mut self) -> Option { @@ -64,22 +66,32 @@ impl<'a> Iterator for EdgeTableIterator<'a> { /// An immutable view of an edge table. /// -/// These are not created directly. -/// Instead, use [`TableAccess::edges`](crate::TableAccess::edges) -/// to get a reference to an existing edge table; +/// These are not created directly but are accessed +/// by types implementing [`std::ops::Deref`] to +/// [`crate::table_views::TableViews`] #[repr(transparent)] -pub struct EdgeTable<'a> { - table_: &'a ll_bindings::tsk_edge_table_t, +pub struct EdgeTable { + pub(crate) table_: NonNull, } -impl<'a> EdgeTable<'a> { - pub(crate) fn new_from_table(edges: &'a ll_bindings::tsk_edge_table_t) -> Self { - EdgeTable { table_: edges } +impl EdgeTable { + pub(crate) fn new_from_table( + edges: *mut ll_bindings::tsk_edge_table_t, + ) -> Result { + let n = NonNull::new(edges).ok_or_else(|| { + TskitError::LibraryError("null pointer to tsk_edge_table_t".to_string()) + })?; + Ok(EdgeTable { table_: n }) + } + + pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_edge_table_t { + // SAFETY: NonNull + unsafe { self.table_.as_ref() } } /// Return the number of rows - pub fn num_rows(&'a self) -> crate::SizeType { - self.table_.num_rows.into() + pub fn num_rows(&self) -> crate::SizeType { + self.as_ref().num_rows.into() } /// Return the ``parent`` value from row ``row`` of the table. @@ -88,12 +100,12 @@ impl<'a> EdgeTable<'a> { /// /// * `Some(parent)` if `u` is valid. /// * `None` otherwise. - pub fn parent + Copy>(&'a self, row: E) -> Option { + pub fn parent + Copy>(&self, row: E) -> Option { unsafe_tsk_column_access!( row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), parent, NodeId ) @@ -105,8 +117,15 @@ impl<'a> EdgeTable<'a> { /// /// * `Some(child)` if `u` is valid. /// * `None` otherwise. - pub fn child + Copy>(&'a self, row: E) -> Option { - unsafe_tsk_column_access!(row.into().0, 0, self.num_rows(), self.table_, child, NodeId) + pub fn child + Copy>(&self, row: E) -> Option { + unsafe_tsk_column_access!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + child, + NodeId + ) } /// Return the ``left`` value from row ``row`` of the table. @@ -115,12 +134,12 @@ impl<'a> EdgeTable<'a> { /// /// * `Some(position)` if `u` is valid. /// * `None` otherwise. - pub fn left + Copy>(&'a self, row: E) -> Option { + pub fn left + Copy>(&self, row: E) -> Option { unsafe_tsk_column_access!( row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), left, Position ) @@ -132,8 +151,14 @@ impl<'a> EdgeTable<'a> { /// /// * `Some(position)` if `u` is valid. /// * `None` otherwise. - pub fn right + Copy>(&'a self, row: E) -> Option { - unsafe_tsk_column_access_and_map_into!(row.into().0, 0, self.num_rows(), self.table_, right) + pub fn right + Copy>(&self, row: E) -> Option { + unsafe_tsk_column_access_and_map_into!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + right + ) } /// Retrieve decoded metadata for a `row`. @@ -153,10 +178,10 @@ impl<'a> EdgeTable<'a> { /// The big-picture semantics are the same for all table types. /// See [`crate::IndividualTable::metadata`] for examples. pub fn metadata( - &'a self, + &self, row: EdgeId, ) -> Option> { - let table_ref = self.table_; + let table_ref = self.as_ref(); let buffer = metadata_to_vector!(self, table_ref, row.0)?; Some(decode_metadata_row!(T, buffer).map_err(|e| e.into())) } @@ -165,7 +190,7 @@ impl<'a> EdgeTable<'a> { /// The value of the iterator is [`EdgeTableRow`]. /// pub fn iter(&self) -> impl Iterator + '_ { - crate::table_iterator::make_table_iterator::<&EdgeTable<'a>>(self) + crate::table_iterator::make_table_iterator::<&EdgeTable>(self) } /// Return row `r` of the table. diff --git a/src/individual_table.rs b/src/individual_table.rs index c233b7102..9014f42d5 100644 --- a/src/individual_table.rs +++ b/src/individual_table.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use crate::bindings as ll_bindings; use crate::metadata; use crate::IndividualFlags; @@ -45,15 +47,15 @@ impl PartialEq for IndividualTableRow { /// An immutable view of a individual table. /// -/// These are not created directly. -/// Instead, use [`TableAccess::individuals`](crate::TableAccess::individuals) -/// to get a reference to an existing node table; -pub struct IndividualTable<'a> { - table_: &'a ll_bindings::tsk_individual_table_t, +/// These are not created directly but are accessed +/// by types implementing [`std::ops::Deref`] to +/// [`crate::table_views::TableViews`] +pub struct IndividualTable { + table_: NonNull, } fn make_individual_table_row(table: &IndividualTable, pos: tsk_id_t) -> Option { - let table_ref = table.table_; + let table_ref = table.as_ref(); Some(IndividualTableRow { id: pos.into(), flags: table.flags(pos)?, @@ -64,9 +66,8 @@ fn make_individual_table_row(table: &IndividualTable, pos: tsk_id_t) -> Option = - crate::table_iterator::TableIterator<&'a IndividualTable<'a>>; -pub(crate) type IndividualTableIterator<'a> = - crate::table_iterator::TableIterator>; + crate::table_iterator::TableIterator<&'a IndividualTable>; +pub(crate) type IndividualTableIterator = crate::table_iterator::TableIterator; impl<'a> Iterator for IndividualTableRefIterator<'a> { type Item = IndividualTableRow; @@ -78,7 +79,7 @@ impl<'a> Iterator for IndividualTableRefIterator<'a> { } } -impl<'a> Iterator for IndividualTableIterator<'a> { +impl Iterator for IndividualTableIterator { type Item = IndividualTableRow; fn next(&mut self) -> Option { @@ -88,16 +89,24 @@ impl<'a> Iterator for IndividualTableIterator<'a> { } } -impl<'a> IndividualTable<'a> { - pub(crate) fn new_from_table(individuals: &'a ll_bindings::tsk_individual_table_t) -> Self { - IndividualTable { - table_: individuals, - } +impl IndividualTable { + pub(crate) fn new_from_table( + individuals: *mut ll_bindings::tsk_individual_table_t, + ) -> Result { + let n = NonNull::new(individuals).ok_or_else(|| { + TskitError::LibraryError("null pointer to tsk_individual_table_t".to_string()) + })?; + Ok(IndividualTable { table_: n }) + } + + pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_individual_table_t { + // SAFETY: NonNull + unsafe { self.table_.as_ref() } } /// Return the number of rows - pub fn num_rows(&'a self) -> crate::SizeType { - self.table_.num_rows.into() + pub fn num_rows(&self) -> crate::SizeType { + self.as_ref().num_rows.into() } /// Return the flags for a given row. @@ -107,7 +116,13 @@ impl<'a> IndividualTable<'a> { /// * `Some(flags)` if `row` is valid. /// * `None` otherwise. pub fn flags + Copy>(&self, row: I) -> Option { - unsafe_tsk_column_access_and_map_into!(row.into().0, 0, self.num_rows(), self.table_, flags) + unsafe_tsk_column_access_and_map_into!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + flags + ) } /// Return the locations for a given row. @@ -121,7 +136,7 @@ impl<'a> IndividualTable<'a> { row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), location, location_offset, location_length, @@ -140,7 +155,7 @@ impl<'a> IndividualTable<'a> { row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), parents, parents_offset, parents_length, @@ -179,7 +194,7 @@ impl<'a> IndividualTable<'a> { /// /// ``` /// # #[cfg(feature = "derive")] { - /// # use tskit::TableAccess; + /// # /// # let mut tables = tskit::TableCollection::new(100.).unwrap(); /// # #[derive(serde::Serialize, serde::Deserialize, tskit::metadata::IndividualMetadata)] /// # #[serializer("serde_json")] @@ -202,7 +217,7 @@ impl<'a> IndividualTable<'a> { /// /// ``` /// # #[cfg(feature = "derive")] { - /// # use tskit::TableAccess; + /// # /// # let mut tables = tskit::TableCollection::new(100.).unwrap(); /// # #[derive(serde::Serialize, serde::Deserialize, tskit::metadata::IndividualMetadata)] /// # #[serializer("serde_json")] @@ -248,7 +263,7 @@ impl<'a> IndividualTable<'a> { # struct MutationMetadata { # x: i32, # } -# use tskit::TableAccess; +# # let mut tables = tskit::TableCollection::new(10.).unwrap(); match tables.individuals().metadata::(0.into()) { @@ -280,7 +295,7 @@ match tables.individuals().metadata::(0.into()) /// /// ``` /// # #[cfg(feature = "derive")] { - /// # use tskit::TableAccess; + /// # /// # #[derive(serde::Serialize, serde::Deserialize, tskit::metadata::IndividualMetadata)] /// # #[serializer("serde_json")] /// # struct IndividualMetadata { @@ -319,10 +334,10 @@ match tables.individuals().metadata::(0.into()) /// types](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types) to enforce at *compile time* that exactly one type (`struct/enum`, etc.) is a valid /// metadata type for a table. pub fn metadata( - &'a self, + &self, row: IndividualId, ) -> Option> { - let table_ref = self.table_; + let table_ref = self.as_ref(); let buffer = metadata_to_vector!(self, table_ref, row.0)?; Some(decode_metadata_row!(T, buffer).map_err(|e| e.into())) } @@ -331,7 +346,7 @@ match tables.individuals().metadata::(0.into()) /// The value of the iterator is [`IndividualTableRow`]. /// pub fn iter(&self) -> impl Iterator + '_ { - crate::table_iterator::make_table_iterator::<&IndividualTable<'a>>(self) + crate::table_iterator::make_table_iterator::<&IndividualTable>(self) } /// Return row `r` of the table. diff --git a/src/lib.rs b/src/lib.rs index f596e5b23..40138b398 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ pub mod prelude; mod site_table; mod table_collection; mod table_iterator; +pub mod table_views; mod traits; mod tree_interface; mod trees; @@ -438,8 +439,6 @@ pub use site_table::{OwnedSiteTable, SiteTable, SiteTableRow}; pub use table_collection::TableCollection; pub use traits::IndividualLocation; pub use traits::IndividualParents; -pub use traits::NodeListGenerator; -pub use traits::TableAccess; pub use traits::TskitTypeAccess; pub use tree_interface::{NodeTraversalOrder, TreeInterface}; pub use trees::{Tree, TreeSequence}; diff --git a/src/metadata.rs b/src/metadata.rs index bc81bbf22..f448a64c2 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -30,7 +30,7 @@ //! ``` //! # #[cfg(feature = "derive")] { //! use tskit::handle_metadata_return; -//! use tskit::TableAccess; +//! //! //! #[derive(serde::Serialize, serde::Deserialize, tskit::metadata::MutationMetadata)] //! #[serializer("serde_json")] @@ -75,7 +75,7 @@ //! //! ``` //! # #[cfg(feature = "derive")] { -//! use tskit::TableAccess; +//! //! #[derive(serde::Serialize, serde::Deserialize, PartialEq, PartialOrd)] //! struct GeneticValue(f64); //! @@ -101,7 +101,7 @@ //! For fun, we'll use the Python [`pickle`](https://docs.rs/crate/serde-pickle/) format. //! //! ``` -//! use tskit::TableAccess; +//! //! //! #[derive(serde::Serialize, serde::Deserialize)] //! struct Metadata { diff --git a/src/migration_table.rs b/src/migration_table.rs index 41285cd3d..1adbbd240 100644 --- a/src/migration_table.rs +++ b/src/migration_table.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use crate::bindings as ll_bindings; use crate::metadata; use crate::Position; @@ -34,7 +36,7 @@ impl PartialEq for MigrationTableRow { } fn make_migration_table_row(table: &MigrationTable, pos: tsk_id_t) -> Option { - let table_ref = table.table_; + let table_ref = table.as_ref(); Some(MigrationTableRow { id: pos.into(), left: table.left(pos)?, @@ -48,9 +50,8 @@ fn make_migration_table_row(table: &MigrationTable, pos: tsk_id_t) -> Option = - crate::table_iterator::TableIterator<&'a MigrationTable<'a>>; -pub(crate) type MigrationTableIterator<'a> = - crate::table_iterator::TableIterator>; + crate::table_iterator::TableIterator<&'a MigrationTable>; +pub(crate) type MigrationTableIterator = crate::table_iterator::TableIterator; impl<'a> Iterator for MigrationTableRefIterator<'a> { type Item = MigrationTableRow; @@ -62,7 +63,7 @@ impl<'a> Iterator for MigrationTableRefIterator<'a> { } } -impl<'a> Iterator for MigrationTableIterator<'a> { +impl Iterator for MigrationTableIterator { type Item = crate::migration_table::MigrationTableRow; fn next(&mut self) -> Option { @@ -74,21 +75,31 @@ impl<'a> Iterator for MigrationTableIterator<'a> { /// An immutable view of a migration table. /// -/// These are not created directly. -/// Instead, use [`TableAccess::migrations`](crate::TableAccess::migrations) -/// to get a reference to an existing node table; -pub struct MigrationTable<'a> { - table_: &'a ll_bindings::tsk_migration_table_t, +/// These are not created directly but are accessed +/// by types implementing [`std::ops::Deref`] to +/// [`crate::table_views::TableViews`] +pub struct MigrationTable { + table_: NonNull, } -impl<'a> MigrationTable<'a> { - pub(crate) fn new_from_table(migrations: &'a ll_bindings::tsk_migration_table_t) -> Self { - MigrationTable { table_: migrations } +impl MigrationTable { + pub(crate) fn new_from_table( + migrations: *mut ll_bindings::tsk_migration_table_t, + ) -> Result { + let n = NonNull::new(migrations).ok_or_else(|| { + TskitError::LibraryError("null pointer to tsk_migration_table_t".to_string()) + })?; + Ok(MigrationTable { table_: n }) + } + + pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_migration_table_t { + // SAFETY: NonNull + unsafe { self.table_.as_ref() } } /// Return the number of rows - pub fn num_rows(&'a self) -> SizeType { - self.table_.num_rows.into() + pub fn num_rows(&self) -> SizeType { + self.as_ref().num_rows.into() } /// Return the left coordinate for a given row. @@ -97,8 +108,14 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(position)` if `row` is valid. /// * `None` otherwise. - pub fn left + Copy>(&'a self, row: M) -> Option { - unsafe_tsk_column_access_and_map_into!(row.into().0, 0, self.num_rows(), self.table_, left) + pub fn left + Copy>(&self, row: M) -> Option { + unsafe_tsk_column_access_and_map_into!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + left + ) } /// Return the right coordinate for a given row. @@ -107,8 +124,14 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(positions)` if `row` is valid. /// * `None` otherwise. - pub fn right + Copy>(&'a self, row: M) -> Option { - unsafe_tsk_column_access_and_map_into!(row.into().0, 0, self.num_rows(), self.table_, right) + pub fn right + Copy>(&self, row: M) -> Option { + unsafe_tsk_column_access_and_map_into!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + right + ) } /// Return the node for a given row. @@ -117,8 +140,15 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(node)` if `row` is valid. /// * `None` otherwise. - pub fn node + Copy>(&'a self, row: M) -> Option { - unsafe_tsk_column_access!(row.into().0, 0, self.num_rows(), self.table_, node, NodeId) + pub fn node + Copy>(&self, row: M) -> Option { + unsafe_tsk_column_access!( + row.into().0, + 0, + self.num_rows(), + self.as_ref(), + node, + NodeId + ) } /// Return the source population for a given row. @@ -127,12 +157,12 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(population)` if `row` is valid. /// * `None` otherwise. - pub fn source + Copy>(&'a self, row: M) -> Option { + pub fn source + Copy>(&self, row: M) -> Option { unsafe_tsk_column_access!( row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), source, PopulationId ) @@ -144,12 +174,12 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(population)` if `row` is valid. /// * `None` otherwise. - pub fn dest + Copy>(&'a self, row: M) -> Option { + pub fn dest + Copy>(&self, row: M) -> Option { unsafe_tsk_column_access!( row.into().0, 0, self.num_rows(), - self.table_, + self.as_ref(), dest, PopulationId ) @@ -161,8 +191,14 @@ impl<'a> MigrationTable<'a> { /// /// * `Some(time)` if `row` is valid. /// * `None` otherwise. - pub fn time + Copy>(&'a self, row: M) -> Option