Skip to content

Commit 2a8bd7e

Browse files
committed
feat: Add tskit::OwnedNodeTable
1 parent 8459375 commit 2a8bd7e

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ pub use flags::*;
428428
pub use individual_table::{IndividualTable, IndividualTableRow};
429429
pub use migration_table::{MigrationTable, MigrationTableRow};
430430
pub use mutation_table::{MutationTable, MutationTableRow};
431-
pub use node_table::{NodeTable, NodeTableRow};
431+
pub use node_table::{NodeTable, NodeTableRow, OwnedNodeTable};
432432
pub use population_table::{OwnedPopulationTable, PopulationTable, PopulationTableRow};
433433
pub use site_table::{SiteTable, SiteTableRow};
434434
pub use table_collection::TableCollection;

src/node_table.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::SizeType;
55
use crate::Time;
66
use crate::{tsk_id_t, TskitError};
77
use crate::{IndividualId, NodeId, PopulationId};
8+
use ll_bindings::{tsk_node_table_free, tsk_node_table_init};
89

910
/// Row of a [`NodeTable`]
1011
pub struct NodeTableRow {
@@ -243,3 +244,121 @@ impl<'a> NodeTable<'a> {
243244
samples
244245
}
245246
}
247+
248+
/// A standalone node table that owns its data.
249+
///
250+
/// # Examples
251+
///
252+
/// ```
253+
/// use tskit::OwnedNodeTable;
254+
///
255+
/// let mut nodes = OwnedNodeTable::default();
256+
/// let rowid = nodes.add_row(0, 1.1, -1, -1).unwrap();
257+
/// assert_eq!(rowid, 0);
258+
/// assert_eq!(nodes.num_rows(), 1);
259+
/// ```
260+
///
261+
/// An example with metadata.
262+
/// This requires the cargo feature `"derive"` for `tskit`.
263+
///
264+
/// ```
265+
/// # #[cfg(any(feature="doc", feature="derive"))] {
266+
/// use tskit::OwnedNodeTable;
267+
///
268+
/// #[derive(serde::Serialize,
269+
/// serde::Deserialize,
270+
/// tskit::metadata::NodeMetadata)]
271+
/// #[serializer("serde_json")]
272+
/// struct NodeMetadata {
273+
/// value: i32,
274+
/// }
275+
///
276+
/// let metadata = NodeMetadata{value: 42};
277+
///
278+
/// let mut nodes = OwnedNodeTable::default();
279+
///
280+
/// let rowid = nodes.add_row_with_metadata(0, 1., -1, -1, &metadata).unwrap();
281+
/// assert_eq!(rowid, 0);
282+
///
283+
/// if let Some(decoded) = nodes.metadata::<NodeMetadata>(rowid).unwrap() {
284+
/// assert_eq!(decoded.value, 42);
285+
/// } else {
286+
/// panic!("hmm...we expected some metadata!");
287+
/// }
288+
///
289+
/// # }
290+
/// ```
291+
pub struct OwnedNodeTable {
292+
table: mbox::MBox<ll_bindings::tsk_node_table_t>,
293+
}
294+
295+
impl OwnedNodeTable {
296+
pub fn add_row(
297+
&mut self,
298+
flags: impl Into<NodeFlags>,
299+
time: impl Into<Time>,
300+
population: impl Into<PopulationId>,
301+
individual: impl Into<IndividualId>,
302+
) -> Result<NodeId, TskitError> {
303+
let rv = unsafe {
304+
ll_bindings::tsk_node_table_add_row(
305+
&mut (*self.table),
306+
flags.into().bits(),
307+
time.into().0,
308+
population.into().0,
309+
individual.into().0,
310+
std::ptr::null(),
311+
0,
312+
)
313+
};
314+
315+
handle_tsk_return_value!(rv, rv.into())
316+
}
317+
318+
pub fn add_row_with_metadata<M>(
319+
&mut self,
320+
flags: impl Into<NodeFlags>,
321+
time: impl Into<Time>,
322+
population: impl Into<PopulationId>,
323+
individual: impl Into<IndividualId>,
324+
metadata: &M,
325+
) -> Result<NodeId, TskitError>
326+
where
327+
M: crate::metadata::NodeMetadata,
328+
{
329+
let md = crate::metadata::EncodedMetadata::new(metadata)?;
330+
let rv = unsafe {
331+
ll_bindings::tsk_node_table_add_row(
332+
&mut (*self.table),
333+
flags.into().bits(),
334+
time.into().0,
335+
population.into().0,
336+
individual.into().0,
337+
md.as_ptr(),
338+
md.len().into(),
339+
)
340+
};
341+
handle_tsk_return_value!(rv, rv.into())
342+
}
343+
}
344+
345+
build_owned_tables!(
346+
OwnedNodeTable,
347+
NodeTable,
348+
ll_bindings::tsk_node_table_t,
349+
tsk_node_table_init,
350+
tsk_node_table_free
351+
);
352+
353+
#[cfg(test)]
354+
mod test_owned_node_table {
355+
use super::*;
356+
357+
#[test]
358+
fn test_add_row() {
359+
let mut nodes = OwnedNodeTable::default();
360+
let rowid = nodes.add_row(0, 1.1, -1, -1).unwrap();
361+
assert_eq!(rowid, 0);
362+
assert_eq!(nodes.num_rows(), 1);
363+
}
364+
}

0 commit comments

Comments
 (0)