@@ -165,3 +165,213 @@ fn get_data_from_edge_table() {
165
165
. check_integrity( tskit:: TableIntegrityCheckFlags :: default ( ) )
166
166
. is_ok( ) ) ;
167
167
}
168
+
169
+ #[ test]
170
+ fn test_adding_node_table_row_with_defaults ( ) {
171
+ let mut tables = tskit:: TableCollection :: new ( 10. ) . unwrap ( ) ;
172
+ // ANCHOR: node_defaults
173
+ let defaults = tskit:: NodeDefaults :: default ( ) ;
174
+ // ANCHOR_END: node_defaults
175
+ // ANCHOR: add_node_defaults
176
+ let node = tables. add_node_with_defaults ( 0.0 , & defaults) . unwrap ( ) ;
177
+ // ANCHOR_END: add_node_defaults
178
+ assert_eq ! ( node, 0 ) ;
179
+
180
+ // ANCHOR: add_node_defaults_sample
181
+ let node = tables
182
+ . add_node_with_defaults (
183
+ 0.0 ,
184
+ // Create a new, temporary defaults instance
185
+ & tskit:: NodeDefaults {
186
+ // Mark the new node as a sample
187
+ flags : tskit:: NodeFlags :: new_sample ( ) ,
188
+ // Use remaining values from our current defaults
189
+ ..defaults
190
+ } ,
191
+ )
192
+ . unwrap ( ) ;
193
+ // ANCHOR_END: add_node_defaults_sample
194
+ assert ! ( tables. nodes( ) . flags( node) . unwrap( ) . is_sample( ) ) ;
195
+ }
196
+
197
+ macro_rules! impl_node_metadata_traits {
198
+ ( ) => {
199
+ impl tskit:: metadata:: MetadataRoundtrip for NodeMetadata {
200
+ fn encode( & self ) -> Result <Vec <u8 >, tskit:: metadata:: MetadataError > {
201
+ match serde_json:: to_string( self ) {
202
+ Ok ( x) => Ok ( x. as_bytes( ) . to_vec( ) ) ,
203
+ Err ( e) => {
204
+ Err ( :: tskit:: metadata:: MetadataError :: RoundtripError { value: Box :: new( e) } )
205
+ }
206
+ }
207
+ }
208
+ fn decode( md: & [ u8 ] ) -> Result <Self , tskit:: metadata:: MetadataError >
209
+ where
210
+ Self : Sized ,
211
+ {
212
+ match serde_json:: from_slice( md) {
213
+ Ok ( v) => Ok ( v) ,
214
+ Err ( e) => {
215
+ Err ( :: tskit:: metadata:: MetadataError :: RoundtripError { value: Box :: new( e) } )
216
+ }
217
+ }
218
+ }
219
+ }
220
+ impl tskit:: metadata:: NodeMetadata for NodeMetadata { }
221
+ } ;
222
+ }
223
+
224
+ mod node_metadata {
225
+ #[ derive( Debug , serde:: Serialize , serde:: Deserialize , Eq , PartialEq ) ]
226
+ // ANCHOR: node_metadata
227
+ pub struct NodeMetadata {
228
+ pub value : i32 ,
229
+ }
230
+ // ANCHOR_END: node_metadata
231
+ impl_node_metadata_traits ! ( ) ;
232
+ }
233
+
234
+ mod node_metadata_clone {
235
+ #[ derive( Debug , Eq , PartialEq , Clone , serde:: Serialize , serde:: Deserialize ) ]
236
+ pub struct NodeMetadata {
237
+ pub value : i32 ,
238
+ }
239
+ impl_node_metadata_traits ! ( ) ;
240
+ }
241
+
242
+ #[ test]
243
+ fn test_adding_node_table_row_with_defaults_and_metadata ( ) {
244
+ use node_metadata:: NodeMetadata ;
245
+ let mut tables = tskit:: TableCollection :: new ( 10.0 ) . unwrap ( ) ;
246
+ // ANCHOR: node_defaults_with_metadata
247
+
248
+ // Create a type alias for brevity
249
+ type DefaultsWithMetadata = tskit:: NodeDefaultsWithMetadata < NodeMetadata > ;
250
+ // Default metadata is None
251
+ let defaults = DefaultsWithMetadata :: default ( ) ;
252
+
253
+ // A row with no metadata
254
+ let n0 = tables. add_node_with_defaults ( 0.0 , & defaults) . unwrap ( ) ;
255
+
256
+ // A row with metadata
257
+ let n1 = tables
258
+ . add_node_with_defaults (
259
+ 0.0 ,
260
+ & DefaultsWithMetadata {
261
+ population : 3 . into ( ) ,
262
+ metadata : Some ( NodeMetadata { value : 42 } ) ,
263
+ ..defaults
264
+ } ,
265
+ )
266
+ . unwrap ( ) ;
267
+
268
+ // Another row with metadata, different from the last.
269
+ let n2 = tables
270
+ . add_node_with_defaults (
271
+ 0.0 ,
272
+ & DefaultsWithMetadata {
273
+ population : 1 . into ( ) ,
274
+ metadata : Some ( NodeMetadata { value : 1234 } ) ,
275
+ ..defaults
276
+ } ,
277
+ )
278
+ . unwrap ( ) ;
279
+ // ANCHOR_END: node_defaults_with_metadata
280
+ assert ! ( tables. nodes( ) . metadata:: <NodeMetadata >( n0) . is_none( ) ) ;
281
+ assert_eq ! (
282
+ tables
283
+ . nodes( )
284
+ . metadata:: <NodeMetadata >( n1)
285
+ . unwrap( )
286
+ . unwrap( ) ,
287
+ NodeMetadata { value: 42 }
288
+ ) ;
289
+ assert_eq ! (
290
+ tables
291
+ . nodes( )
292
+ . metadata:: <NodeMetadata >( n2)
293
+ . unwrap( )
294
+ . unwrap( ) ,
295
+ NodeMetadata { value: 1234 }
296
+ ) ;
297
+ }
298
+
299
+ #[ test]
300
+ fn test_adding_node_table_row_with_defaults_and_metadata_requiring_clone ( ) {
301
+ use node_metadata_clone:: NodeMetadata ;
302
+ let mut tables = tskit:: TableCollection :: new ( 10.0 ) . unwrap ( ) ;
303
+ type DefaultsWithMetadata = tskit:: NodeDefaultsWithMetadata < NodeMetadata > ;
304
+
305
+ // ANCHOR: node_defaults_with_some_metadata_default
306
+ // What if there is default metadata for all rows?
307
+ let defaults = DefaultsWithMetadata {
308
+ metadata : Some ( NodeMetadata { value : 42 } ) ,
309
+ ..Default :: default ( )
310
+ } ;
311
+ // ANCHOR_END: node_defaults_with_some_metadata_default
312
+
313
+ // ANCHOR: node_defaults_with_some_metadata_default_add_first_row
314
+ let n0 = tables
315
+ . add_node_with_defaults (
316
+ 0.0 ,
317
+ & DefaultsWithMetadata {
318
+ metadata : Some ( NodeMetadata { value : 2 * 42 } ) ,
319
+ ..defaults
320
+ } ,
321
+ )
322
+ . unwrap ( ) ;
323
+ // ANCHOR_END: node_defaults_with_some_metadata_default_add_first_row
324
+ assert_eq ! (
325
+ tables
326
+ . nodes( )
327
+ . metadata:: <NodeMetadata >( n0)
328
+ . unwrap( )
329
+ . unwrap( ) ,
330
+ NodeMetadata { value: 2 * 42 }
331
+ ) ;
332
+
333
+ // But now, we start to cause a problem:
334
+ // If we don't clone here, our metadata type moves,
335
+ // so our defaults are moved.
336
+ // ANCHOR: node_defaults_with_some_metadata_default_add_second_row
337
+ let n1 = tables
338
+ . add_node_with_defaults (
339
+ 0.0 ,
340
+ & DefaultsWithMetadata {
341
+ population : 6 . into ( ) ,
342
+ ..defaults. clone ( )
343
+ } ,
344
+ )
345
+ . unwrap ( ) ;
346
+ // ANCHOR_END: node_defaults_with_some_metadata_default_add_second_row
347
+ assert_eq ! (
348
+ tables
349
+ . nodes( )
350
+ . metadata:: <NodeMetadata >( n1)
351
+ . unwrap( )
352
+ . unwrap( ) ,
353
+ NodeMetadata { value: 42 }
354
+ ) ;
355
+
356
+ // Now, we have a use-after-move error
357
+ // if we hadn't cloned in the last step.
358
+ // ANCHOR: node_defaults_with_some_metadata_default_add_third_row
359
+ let n2 = tables
360
+ . add_node_with_defaults (
361
+ 0.0 ,
362
+ & DefaultsWithMetadata {
363
+ individual : 7 . into ( ) ,
364
+ ..defaults
365
+ } ,
366
+ )
367
+ . unwrap ( ) ;
368
+ // ANCHOR_END: node_defaults_with_some_metadata_default_add_third_row
369
+ assert_eq ! (
370
+ tables
371
+ . nodes( )
372
+ . metadata:: <NodeMetadata >( n2)
373
+ . unwrap( )
374
+ . unwrap( ) ,
375
+ NodeMetadata { value: 42 }
376
+ ) ;
377
+ }
0 commit comments