@@ -5,6 +5,7 @@ use crate::SizeType;
55use crate :: Time ;
66use crate :: { tsk_id_t, TskitError } ;
77use crate :: { IndividualId , NodeId , PopulationId } ;
8+ use ll_bindings:: { tsk_node_table_free, tsk_node_table_init} ;
89
910/// Row of a [`NodeTable`]
1011pub 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