tskit/lib.rs
1//! A rust interface to [tskit](https://github.com/tskit-dev/tskit).
2//!
3//! This crate provides a mapping of the `tskit` C API to rust.
4//! The result is an interface similar to the `tskit` Python interface,
5//! but with all operations implemented using compiled code.
6//!
7//! # Features
8//!
9//! ## Interface to the C library
10//!
11//! * [`TableCollection`] wraps `tsk_table_collection_t`.
12//! * [`TreeSequence`] wraps `tsk_treeseq_t`.
13//! * [`Tree`] wraps `tsk_tree_t`.
14//! * Tree iteration occurs via traits from [streaming_iterator](https://docs.rs/streaming-iterator/).
15//! * Errors returned from C map to [`TskitError::ErrorCode`].
16//! Their string messages can be obtained by printing the error type.
17//!
18//! ## Safety
19//!
20//! * The types listed above handle all the memory management!
21//! * All array accesses are range-checked.
22//! * Object lifetimes are clear:
23//! * Creating a tree sequence moves/consumes a table collection.
24//! * Tree lifetimes are tied to that of the parent tree sequence.
25//! * Table objects ([`NodeTable`], etc..) are only represented by non-owning, immutable types.
26//!
27//! ## Prelude
28//!
29//! The [`prelude`] module contains definitions that are difficult/annoying to live without.
30//! In particuar, this module exports various traits that make it so that client code does
31//! not have to `use` them a la carte.
32//!
33//! We recomment that client code import all symbols from this module:
34//!
35//! ```
36//! use tskit::prelude::*;
37//! ```
38//!
39//! The various documentation examples manually `use` each trait both in order
40//! to illustrate which traits are needed and to serve as doc tests.
41//!
42//! # Optional features
43//!
44//! Some features are optional, and are activated by requesting them in your `Cargo.toml` file.
45//!
46//! * `provenance`
47//! * Enables `provenance`
48//! * `derive` enables the following derive macros:
49//! * [`crate::metadata::MutationMetadata`]
50//! * [`crate::metadata::IndividualMetadata`]
51//! * [`crate::metadata::SiteMetadata`]
52//! * [`crate::metadata::EdgeMetadata`]
53//! * [`crate::metadata::NodeMetadata`]
54//! * [`crate::metadata::MigrationMetadata`]
55//! * [`crate::metadata::PopulationMetadata`]
56//!
57//! To see these derive macros in action, take a look
58//! [`here`](metadata).
59//! * `unsafe_init` enables [`crate::TableCollection::new_from_raw`]
60//!
61//! To add features to your `Cargo.toml` file:
62//!
63//! ```toml
64//! [dependencies]
65//! tskit = {version = "0.2.0", features=["feature0", "feature1"]}
66//! ```
67//!
68//! # Table rows and iterators over rows
69//!
70//! ## Background: what is going on at the `C` level
71//!
72//! The `C` API represents a row as a `struct` containing
73//! various fields.
74//! For example, a "mutation" (row of a mutation table) is
75//! represented by [`crate::bindings::tsk_mutation_t`].
76//!
77//! These low-level types contain pointers into ragged arrays
78//! such as metadata.
79//! These pointers do *not* point to new allocations.
80//! Rather, they point to subsets of the ragged arrays
81//! found in the parent objects (tables).
82//!
83//! The API to populate the row types is to first allocate one
84//! (either on the stack or on the heap) and then call a function.
85//! For example, [`crate::bindings::tsk_mutation_table_get_row`]
86//! will fill in the fields of a [`crate::bindings::tsk_mutation_t`].
87//!
88//! The challenge on the rust side is how to specify the lifetime
89//! relationship between a row object and its parent object.
90//!
91//! ### Differences between table collections and tree sequences
92//!
93//! The row types mentioned above can be accessed from table collections
94//! and from tree sequences.
95//!
96//! However, tree sequence initialization pre-computes site and mutation
97//! objects as well as the nodes associated with individuals.
98//! Therefore, we can obtain constant-time access to references to site
99//! and mutation objects from a tree sequence.
100//!
101//! The situation for objects directly from table collections poses
102//! a challenge.
103//! We could re-use an instance of a row object for, say,
104//! a "mutation table row iterator" type, but doing so
105//! would result in incorrect data if the output values were stored.
106//! (Re-use would mean that the pointers to metadata, etc., would get
107//! re-written at each "turn" of the iterator.)
108//! Therefore, when accessing from *tables*, we return new instances
109//! of the low level types.
110//!
111//! ## The relevant rust types
112//!
113//! For tables:
114//!
115//! * [`Node`] is returned by [`NodeTable::row`] and is the iterator value of [`NodeTable::iter`]
116//! and [`TableCollection::node_iter`].
117//! * [`Edge`] is returned by [`EdgeTable::row`] and is the iterator value of [`EdgeTable::iter`]
118//! and [`TableCollection::edge_iter`].
119//! * [`Individual`] is returned by [`IndividualTable::row`] and is the iterator value of [`IndividualTable::iter`]
120//! and [`TableCollection::individual_iter`].
121//! * [`Site`] is returned by [`SiteTable::row`] and is the iterator value of [`SiteTable::iter`]
122//! and [`TableCollection::site_iter`].
123//! * [`Mutation`] is returned by [`MutationTable::row`] and is the iterator value of [`MutationTable::iter`]
124//! and [`TableCollection::mutation_iter`].
125//! * [`Population`] is returned by [`PopulationTable::row`] and is the iterator value of [`PopulationTable::iter`]
126//! and [`TableCollection::population_iter`].
127//! * [`Migration`] is returned by [`MigrationTable::row`] and is the iterator value of [`MigrationTable::iter`]
128//! and [`TableCollection::migration_iter`].
129//! * [`Provenance`] is returned by [`provenance::ProvenanceTable::row`] and is the iterator value of [`provenance::ProvenanceTable::iter`]
130//! and [`TableCollection::provenance_iter`].
131//!
132//! These types are thin wrappers around the `C` types and have the same `sizeof` and alignment.
133//!
134//! For table collections and trees:
135//!
136//! * [`SiteRef`] and [`MutationRef`] replace [`Site`] and [`Mutation`], respectively.
137//! * [`SiteRef`] is the output of [`TreeSequence::site_iter`] and [`Tree::site_iter`].
138//! * [`MutationRef`] is the output of [`SiteRef::mutation_iter`].
139//!
140//! These "`Ref`" types are thin wrappers around shared references to the underlying `C` types.
141//!
142//! Further,
143//!
144//! * [`TreeSequence::individual_iter`] outputs [`Individual`] objects whose `nodes` field is
145//! populated (if the individual is associated w/any nodes).
146//!
147//! # What is missing?
148//!
149//! * A lot of wrappers to the C functions.
150//! * Tree sequence statistics!
151//!
152//! # Manual
153//!
154//! A manual is [here](https://tskit-dev.github.io/tskit-rust).
155
156#![allow(non_upper_case_globals)]
157#![allow(non_camel_case_types)]
158#![allow(non_snake_case)]
159#![cfg_attr(doc_cfg, feature(doc_cfg))]
160#![deny(rustdoc::broken_intra_doc_links)]
161
162use std::ffi::c_char;
163
164#[cfg(feature = "bindings")]
165pub use sys::bindings;
166
167// We have to cast between raw pointers involving these types when handling metadata.
168// These compile-time assertions help prevent undefined behavior in case we run into
169// something unexpected on a specific platform.
170const _: () = const { assert!(std::mem::size_of::<u8>() == std::mem::size_of::<c_char>()) };
171const _: () =
172 const { assert!(std::mem::size_of::<u8>() == std::mem::size_of::<std::ffi::c_char>()) };
173
174pub use streaming_iterator::DoubleEndedStreamingIterator;
175pub use streaming_iterator::StreamingIterator;
176
177mod _macros; // Starts w/_ to be sorted at front by rustfmt!
178mod edge_differences;
179mod edge_table;
180pub mod error;
181mod individual_table;
182pub mod metadata;
183mod migration_table;
184mod mutation_table;
185mod newtypes;
186mod node_table;
187mod population_table;
188pub mod prelude;
189mod site_table;
190mod sys;
191mod table_collection;
192mod table_column;
193mod traits;
194mod trees;
195pub mod types;
196
197pub use edge_differences::*;
198pub use edge_table::EdgeTable;
199pub use error::TskitError;
200pub use individual_table::IndividualTable;
201pub use migration_table::MigrationTable;
202pub use mutation_table::MutationTable;
203pub use newtypes::*;
204pub use node_table::{NodeDefaults, NodeDefaultsWithMetadata, NodeTable};
205pub use population_table::PopulationTable;
206pub use site_table::SiteTable;
207pub use sys::flags::*;
208pub use sys::NodeTraversalOrder;
209pub use table_collection::TableCollection;
210pub use traits::IndividualLocation;
211pub use traits::IndividualParents;
212pub use traits::TableColumn;
213pub use trees::{Tree, TreeSequence};
214
215pub use sys::Edge;
216pub use sys::Individual;
217pub use sys::Migration;
218pub use sys::Mutation;
219pub use sys::MutationRef;
220pub use sys::Node;
221pub use sys::Population;
222#[cfg(feature = "provenance")]
223#[cfg_attr(doc_cfg, doc(cfg(feature = "provenance")))]
224pub use sys::Provenance;
225pub use sys::Site;
226pub use sys::SiteRef;
227
228// Optional features
229#[cfg(feature = "provenance")]
230#[cfg_attr(doc_cfg, doc(cfg(feature = "provenance")))]
231pub mod provenance;
232
233/// Handles return codes from low-level tskit functions.
234///
235/// When an error from the tskit C API is detected,
236/// the error message is stored for diplay.
237pub type TskReturnValue = Result<i32, TskitError>;
238
239/// Alias for tsk_flags_t
240pub type RawFlags = crate::sys::bindings::tsk_flags_t;
241
242/// Version of the rust crate.
243///
244/// To get the C API version, see:
245/// * [`c_api_major_version`]
246/// * [`c_api_minor_version`]
247/// * [`c_api_patch_version`]
248pub fn version() -> &'static str {
249 env!("CARGO_PKG_VERSION")
250}
251
252/// C API major version
253pub fn c_api_major_version() -> u32 {
254 sys::bindings::TSK_VERSION_MAJOR
255}
256
257/// C API minor version
258pub fn c_api_minor_version() -> u32 {
259 sys::bindings::TSK_VERSION_MINOR
260}
261
262/// C API patch version
263pub fn c_api_patch_version() -> u32 {
264 sys::bindings::TSK_VERSION_PATCH
265}
266
267/// The C API version in MAJOR.MINOR.PATCH format
268pub fn c_api_version() -> String {
269 format!(
270 "{}.{}.{}",
271 c_api_major_version(),
272 c_api_minor_version(),
273 c_api_patch_version()
274 )
275}
276
277#[cfg(test)]
278mod tests {
279 use super::c_api_version;
280
281 #[test]
282 fn test_c_api_version() {
283 let _ = c_api_version();
284 }
285}
286
287// Testing modules
288mod test_fixtures;