@@ -165,3 +165,213 @@ fn get_data_from_edge_table() {
165165 . check_integrity( tskit:: TableIntegrityCheckFlags :: default ( ) )
166166 . is_ok( ) ) ;
167167}
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