11use crate :: bindings as ll_bindings;
22use crate :: error:: TskitRustError ;
33use crate :: ffi:: TskitType ;
4+ use crate :: metadata:: * ;
45use crate :: types:: Bookmark ;
56use crate :: EdgeTable ;
67use crate :: MutationTable ;
78use crate :: NodeTable ;
89use crate :: PopulationTable ;
910use crate :: SiteTable ;
1011use crate :: TskReturnValue ;
11- use crate :: { tsk_flags_t, tsk_id_t, tsk_size_t } ;
12+ use crate :: { tsk_flags_t, tsk_id_t} ;
1213use ll_bindings:: tsk_table_collection_free;
1314
1415/// A table collection.
@@ -159,15 +160,28 @@ impl TableCollection {
159160 parent : tsk_id_t ,
160161 child : tsk_id_t ,
161162 ) -> TskReturnValue {
163+ self . add_edge_with_metadata ( left, right, parent, child, None )
164+ }
165+
166+ /// Add a row with metadata to the edge table
167+ pub fn add_edge_with_metadata (
168+ & mut self ,
169+ left : f64 ,
170+ right : f64 ,
171+ parent : tsk_id_t ,
172+ child : tsk_id_t ,
173+ metadata : Option < & dyn MetadataRoundtrip > ,
174+ ) -> TskReturnValue {
175+ let md = EncodedMetadata :: new ( metadata) ?;
162176 let rv = unsafe {
163177 ll_bindings:: tsk_edge_table_add_row (
164178 & mut ( * self . as_mut_ptr ( ) ) . edges ,
165179 left,
166180 right,
167181 parent,
168182 child,
169- std :: ptr :: null ( ) ,
170- 0 ,
183+ md . as_ptr ( ) ,
184+ md . len ( ) ,
171185 )
172186 } ;
173187
@@ -182,15 +196,28 @@ impl TableCollection {
182196 population : tsk_id_t ,
183197 individual : tsk_id_t ,
184198 ) -> TskReturnValue {
199+ self . add_node_witha_metadata ( flags, time, population, individual, None )
200+ }
201+
202+ /// Add a row with metadata to the node table
203+ pub fn add_node_witha_metadata (
204+ & mut self ,
205+ flags : ll_bindings:: tsk_flags_t ,
206+ time : f64 ,
207+ population : tsk_id_t ,
208+ individual : tsk_id_t ,
209+ metadata : Option < & dyn MetadataRoundtrip > ,
210+ ) -> TskReturnValue {
211+ let md = EncodedMetadata :: new ( metadata) ?;
185212 let rv = unsafe {
186213 ll_bindings:: tsk_node_table_add_row (
187214 & mut ( * self . as_mut_ptr ( ) ) . nodes ,
188215 flags,
189216 time,
190217 population,
191218 individual,
192- std :: ptr :: null ( ) ,
193- 0 ,
219+ md . as_ptr ( ) ,
220+ md . len ( ) ,
194221 )
195222 } ;
196223
@@ -199,19 +226,27 @@ impl TableCollection {
199226
200227 /// Add a row to the site table
201228 pub fn add_site ( & mut self , position : f64 , ancestral_state : Option < & [ u8 ] > ) -> TskReturnValue {
202- let astate = match ancestral_state {
203- Some ( x) => ( std:: ffi:: CString :: new ( x) . unwrap ( ) , x. len ( ) as tsk_size_t ) ,
204- None => ( std:: ffi:: CString :: new ( "" . to_string ( ) ) . unwrap ( ) , 0 ) ,
205- } ;
229+ self . add_site_with_metadata ( position, ancestral_state, None )
230+ }
231+
232+ /// Add a row with metadata to the site table
233+ pub fn add_site_with_metadata (
234+ & mut self ,
235+ position : f64 ,
236+ ancestral_state : Option < & [ u8 ] > ,
237+ metadata : Option < & dyn MetadataRoundtrip > ,
238+ ) -> TskReturnValue {
239+ let astate = process_state_input ! ( ancestral_state) ;
240+ let md = EncodedMetadata :: new ( metadata) ?;
206241
207242 let rv = unsafe {
208243 ll_bindings:: tsk_site_table_add_row (
209244 & mut ( * self . as_mut_ptr ( ) ) . sites ,
210245 position,
211- astate. 0 . as_ptr ( ) ,
246+ astate. 0 ,
212247 astate. 1 ,
213- std :: ptr :: null ( ) ,
214- 0 ,
248+ md . as_ptr ( ) ,
249+ md . len ( ) ,
215250 )
216251 } ;
217252
@@ -227,10 +262,21 @@ impl TableCollection {
227262 time : f64 ,
228263 derived_state : Option < & [ u8 ] > ,
229264 ) -> TskReturnValue {
230- let dstate = match derived_state {
231- Some ( x) => ( std:: ffi:: CString :: new ( x) . unwrap ( ) , x. len ( ) as tsk_size_t ) ,
232- None => ( std:: ffi:: CString :: new ( "" . to_string ( ) ) . unwrap ( ) , 0 ) ,
233- } ;
265+ self . add_mutation_with_metadata ( site, node, parent, time, derived_state, None )
266+ }
267+
268+ /// Add a row with metadata to the mutation table.
269+ pub fn add_mutation_with_metadata (
270+ & mut self ,
271+ site : tsk_id_t ,
272+ node : tsk_id_t ,
273+ parent : tsk_id_t ,
274+ time : f64 ,
275+ derived_state : Option < & [ u8 ] > ,
276+ metadata : Option < & dyn MetadataRoundtrip > ,
277+ ) -> TskReturnValue {
278+ let dstate = process_state_input ! ( derived_state) ;
279+ let md = EncodedMetadata :: new ( metadata) ?;
234280
235281 let rv = unsafe {
236282 ll_bindings:: tsk_mutation_table_add_row (
@@ -239,10 +285,10 @@ impl TableCollection {
239285 node,
240286 parent,
241287 time,
242- dstate. 0 . as_ptr ( ) ,
288+ dstate. 0 ,
243289 dstate. 1 ,
244- std :: ptr :: null ( ) ,
245- 0 ,
290+ md . as_ptr ( ) ,
291+ md . len ( ) ,
246292 )
247293 } ;
248294
@@ -251,11 +297,20 @@ impl TableCollection {
251297
252298 /// Add a row to the population_table
253299 pub fn add_population ( & mut self ) -> TskReturnValue {
300+ self . add_population_with_metadata ( None )
301+ }
302+
303+ /// Add a row with metadata to the population_table
304+ pub fn add_population_with_metadata (
305+ & mut self ,
306+ metadata : Option < & dyn MetadataRoundtrip > ,
307+ ) -> TskReturnValue {
308+ let md = EncodedMetadata :: new ( metadata) ?;
254309 let rv = unsafe {
255310 ll_bindings:: tsk_population_table_add_row (
256311 & mut ( * self . as_mut_ptr ( ) ) . populations ,
257- std :: ptr :: null ( ) ,
258- 0 ,
312+ md . as_ptr ( ) ,
313+ md . len ( ) ,
259314 )
260315 } ;
261316
@@ -433,6 +488,49 @@ mod test {
433488 ) ;
434489 }
435490
491+ struct F {
492+ x : i32 ,
493+ y : u32 ,
494+ }
495+
496+ impl MetadataRoundtrip for F {
497+ fn encode ( & self ) -> Result < Vec < u8 > , MetadataError > {
498+ let mut rv = vec ! [ ] ;
499+ rv. extend ( self . x . to_le_bytes ( ) . iter ( ) . map ( |& i| i) ) ;
500+ rv. extend ( self . y . to_le_bytes ( ) . iter ( ) . map ( |& i| i) ) ;
501+ Ok ( rv)
502+ }
503+ fn decode ( md : & [ u8 ] ) -> Result < Self , MetadataError > {
504+ use std:: convert:: TryInto ;
505+ let ( x_int_bytes, rest) = md. split_at ( std:: mem:: size_of :: < i32 > ( ) ) ;
506+ let ( y_int_bytes, _) = rest. split_at ( std:: mem:: size_of :: < u32 > ( ) ) ;
507+ Ok ( Self {
508+ x : i32:: from_le_bytes ( x_int_bytes. try_into ( ) . unwrap ( ) ) ,
509+ y : u32:: from_le_bytes ( y_int_bytes. try_into ( ) . unwrap ( ) ) ,
510+ } )
511+ }
512+ }
513+
514+ #[ test]
515+ fn test_add_mutation_with_metadata ( ) {
516+ let mut tables = TableCollection :: new ( 1000. ) . unwrap ( ) ;
517+ tables
518+ . add_mutation_with_metadata (
519+ 0 ,
520+ 0 ,
521+ crate :: TSK_NULL ,
522+ 1.123 ,
523+ None ,
524+ Some ( & F { x : -3 , y : 666 } ) ,
525+ )
526+ . unwrap ( ) ;
527+ // The double unwrap is to first check for error
528+ // and then to process the Option.
529+ let md = tables. mutations ( ) . metadata :: < F > ( 0 ) . unwrap ( ) . unwrap ( ) ;
530+ assert_eq ! ( md. x, -3 ) ;
531+ assert_eq ! ( md. y, 666 ) ;
532+ }
533+
436534 #[ test]
437535 fn test_add_population ( ) {
438536 let mut tables = TableCollection :: new ( 1000. ) . unwrap ( ) ;
0 commit comments