@@ -138,6 +138,248 @@ impl<'a> streaming_iterator::StreamingIterator for NodeTableRowView<'a> {
138
138
}
139
139
}
140
140
141
+ /// Defaults for node table rows without metadata
142
+ ///
143
+ /// # Examples
144
+ ///
145
+ /// ```
146
+ /// let d = tskit::NodeDefaults::default();
147
+ /// assert_eq!(d.flags, tskit::NodeFlags::default());
148
+ /// assert_eq!(d.population, tskit::PopulationId::NULL);
149
+ /// assert_eq!(d.individual, tskit::IndividualId::NULL);
150
+ /// ```
151
+ ///
152
+ /// [Struct update syntax](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)
153
+ /// is your friend here:
154
+ ///
155
+ /// ```
156
+ /// let d = tskit::NodeDefaults{population: 0.into(), ..Default::default()};
157
+ /// assert_eq!(d.flags, tskit::NodeFlags::default());
158
+ /// assert_eq!(d.population, 0);
159
+ /// assert_eq!(d.individual, tskit::IndividualId::NULL);
160
+ /// let d2 = tskit::NodeDefaults{flags: tskit::NodeFlags::default().mark_sample(),
161
+ /// // update remaining values from d
162
+ /// ..d};
163
+ /// assert!(d2.flags.is_sample());
164
+ /// assert_eq!(d2.population, 0);
165
+ /// assert_eq!(d2.individual, tskit::IndividualId::NULL);
166
+ /// ```
167
+ #[ derive( Copy , Clone , Default , Eq , PartialEq , Debug ) ]
168
+ pub struct NodeDefaults {
169
+ pub flags : NodeFlags ,
170
+ pub population : PopulationId ,
171
+ pub individual : IndividualId ,
172
+ }
173
+
174
+ /// Defaults for node table rows with metadata
175
+ ///
176
+ /// # Notes
177
+ ///
178
+ /// This struct derives `Debug` and `Clone`.
179
+ /// However, neither is a trait bound on `M`.
180
+ /// Therefore, use of `Debug` and/or `Clone` will fail unless `M`
181
+ /// also implements the relevant trait.
182
+ ///
183
+ /// See [the book](https://tskit-dev.github.io/tskit-rust/)
184
+ /// for details.
185
+ #[ derive( Debug , Clone ) ]
186
+ pub struct NodeDefaultsWithMetadata < M >
187
+ where
188
+ M : crate :: metadata:: NodeMetadata ,
189
+ {
190
+ pub flags : NodeFlags ,
191
+ pub population : PopulationId ,
192
+ pub individual : IndividualId ,
193
+ pub metadata : Option < M > ,
194
+ }
195
+
196
+ /// This is a doctest hack as described in the rust book.
197
+ /// We do this b/c the specific error messages can change
198
+ /// across rust versions, making crates like trybuild
199
+ /// less useful.
200
+ ///
201
+ /// ```compile_fail
202
+ /// #[derive(serde::Serialize, serde::Deserialize)]
203
+ /// struct NodeMetadata {
204
+ /// value: i32,
205
+ /// }
206
+ ///
207
+ /// impl tskit::metadata::MetadataRoundtrip for NodeMetadata {
208
+ /// fn encode(&self) -> Result<Vec<u8>, tskit::metadata::MetadataError> {
209
+ /// match serde_json::to_string(self) {
210
+ /// Ok(x) => Ok(x.as_bytes().to_vec()),
211
+ /// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }),
212
+ /// }
213
+ /// }
214
+ /// fn decode(md: &[u8]) -> Result<Self, tskit::metadata::MetadataError>
215
+ /// where
216
+ /// Self: Sized,
217
+ /// {
218
+ /// match serde_json::from_slice(md) {
219
+ /// Ok(v) => Ok(v),
220
+ /// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }),
221
+ /// }
222
+ /// }
223
+ /// }
224
+ ///
225
+ /// impl tskit::metadata::NodeMetadata for NodeMetadata {}
226
+ ///
227
+ /// type DefaultsWithMetadata = tskit::NodeDefaultsWithMetadata<NodeMetadata>;
228
+ /// let defaults = DefaultsWithMetadata {
229
+ /// metadata: Some(NodeMetadata { value: 42 }),
230
+ /// ..Default::default()
231
+ /// };
232
+ ///
233
+ /// // Fails because metadata type is not Debug
234
+ /// println!("{:?}", defaults);
235
+ /// ```
236
+ ///
237
+ /// ```compile_fail
238
+ /// #[derive(serde::Serialize, serde::Deserialize)]
239
+ /// struct NodeMetadata {
240
+ /// value: i32,
241
+ /// }
242
+ ///
243
+ /// impl tskit::metadata::MetadataRoundtrip for NodeMetadata {
244
+ /// fn encode(&self) -> Result<Vec<u8>, tskit::metadata::MetadataError> {
245
+ /// match serde_json::to_string(self) {
246
+ /// Ok(x) => Ok(x.as_bytes().to_vec()),
247
+ /// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }),
248
+ /// }
249
+ /// }
250
+ /// fn decode(md: &[u8]) -> Result<Self, tskit::metadata::MetadataError>
251
+ /// where
252
+ /// Self: Sized,
253
+ /// {
254
+ /// match serde_json::from_slice(md) {
255
+ /// Ok(v) => Ok(v),
256
+ /// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }),
257
+ /// }
258
+ /// }
259
+ /// }
260
+ ///
261
+ /// impl tskit::metadata::NodeMetadata for NodeMetadata {}
262
+ ///
263
+ /// let mut tables = tskit::TableCollection::new(10.0).unwrap();
264
+ /// type DefaultsWithMetadata = tskit::NodeDefaultsWithMetadata<NodeMetadata>;
265
+ /// // What if there is default metadata for all rows?
266
+ /// let defaults = DefaultsWithMetadata {
267
+ /// metadata: Some(NodeMetadata { value: 42 }),
268
+ /// ..Default::default()
269
+ /// };
270
+ /// // We can scoop all non-metadata fields even though
271
+ /// // type is not Copy/Clone
272
+ /// let _ = tables
273
+ /// .add_node_with_defaults(
274
+ /// 0.0,
275
+ /// &DefaultsWithMetadata {
276
+ /// metadata: Some(NodeMetadata { value: 2 * 42 }),
277
+ /// ..defaults
278
+ /// },
279
+ /// )
280
+ /// .unwrap();
281
+ /// // But now, we start to cause a problem:
282
+ /// // If we don't clone here, our metadata type moves,
283
+ /// // so our defaults are moved.
284
+ /// let _ = tables
285
+ /// .add_node_with_defaults(
286
+ /// 0.0,
287
+ /// &DefaultsWithMetadata {
288
+ /// population: 6.into(),
289
+ /// ..defaults
290
+ /// },
291
+ /// )
292
+ /// .unwrap();
293
+ /// // Now, we have a use-after-move error
294
+ /// // if we hadn't cloned in the last step.
295
+ /// let _ = tables
296
+ /// .add_node_with_defaults(
297
+ /// 0.0,
298
+ /// &DefaultsWithMetadata {
299
+ /// individual: 7.into(),
300
+ /// ..defaults
301
+ /// },
302
+ /// )
303
+ /// .unwrap();
304
+ /// ```
305
+ #[ cfg( doctest) ]
306
+ struct NodeDefaultsWithMetadataNotCloneNotDebug ;
307
+
308
+ // Manual implementation required so that
309
+ // we do not force client code to impl Default
310
+ // for metadata types.
311
+ impl < M > Default for NodeDefaultsWithMetadata < M >
312
+ where
313
+ M : crate :: metadata:: NodeMetadata ,
314
+ {
315
+ fn default ( ) -> Self {
316
+ Self {
317
+ flags : NodeFlags :: default ( ) ,
318
+ population : PopulationId :: default ( ) ,
319
+ individual : IndividualId :: default ( ) ,
320
+ metadata : None ,
321
+ }
322
+ }
323
+ }
324
+
325
+ mod private {
326
+ pub trait DefaultNodeDataMarker { }
327
+
328
+ impl DefaultNodeDataMarker for super :: NodeDefaults { }
329
+
330
+ impl < M > DefaultNodeDataMarker for super :: NodeDefaultsWithMetadata < M > where
331
+ M : crate :: metadata:: NodeMetadata
332
+ {
333
+ }
334
+ }
335
+
336
+ /// This trait is sealed.
337
+ pub trait DefaultNodeData : private:: DefaultNodeDataMarker {
338
+ fn flags ( & self ) -> NodeFlags ;
339
+ fn population ( & self ) -> PopulationId ;
340
+ fn individual ( & self ) -> IndividualId ;
341
+ fn metadata ( & self ) -> Result < Option < Vec < u8 > > , TskitError > ;
342
+ }
343
+
344
+ impl DefaultNodeData for NodeDefaults {
345
+ fn flags ( & self ) -> NodeFlags {
346
+ self . flags
347
+ }
348
+ fn population ( & self ) -> PopulationId {
349
+ self . population
350
+ }
351
+ fn individual ( & self ) -> IndividualId {
352
+ self . individual
353
+ }
354
+ fn metadata ( & self ) -> Result < Option < Vec < u8 > > , TskitError > {
355
+ Ok ( None )
356
+ }
357
+ }
358
+
359
+ impl < M > DefaultNodeData for NodeDefaultsWithMetadata < M >
360
+ where
361
+ M : crate :: metadata:: NodeMetadata ,
362
+ {
363
+ fn flags ( & self ) -> NodeFlags {
364
+ self . flags
365
+ }
366
+ fn population ( & self ) -> PopulationId {
367
+ self . population
368
+ }
369
+ fn individual ( & self ) -> IndividualId {
370
+ self . individual
371
+ }
372
+ fn metadata ( & self ) -> Result < Option < Vec < u8 > > , TskitError > {
373
+ self . metadata . as_ref ( ) . map_or_else (
374
+ || Ok ( None ) ,
375
+ |v| match v. encode ( ) {
376
+ Ok ( x) => Ok ( Some ( x) ) ,
377
+ Err ( e) => Err ( e. into ( ) ) ,
378
+ } ,
379
+ )
380
+ }
381
+ }
382
+
141
383
/// A node table.
142
384
///
143
385
/// # Examples
@@ -520,6 +762,71 @@ impl NodeTable {
520
762
)
521
763
}
522
764
765
+ /// Add a row with default values.
766
+ ///
767
+ /// # Parameters
768
+ ///
769
+ /// * `time`, the birth time of the node
770
+ /// * `defaults`, the default values for remaining fields.
771
+ ///
772
+ /// ## Notes on parameters
773
+ ///
774
+ /// The type of `defaults` must be one of:
775
+ ///
776
+ /// * [`NodeDefaults`]
777
+ /// * [`NodeDefaultsWithMetadata`]
778
+ ///
779
+ /// # Examples
780
+ ///
781
+ /// ## Without metadata
782
+ ///
783
+ /// ```
784
+ /// let mut nodes = tskit::NodeTable::default();
785
+ /// let defaults = tskit::NodeDefaults::default();
786
+ /// let id = nodes.add_row_with_defaults(0.0, &defaults).unwrap();
787
+ /// assert_eq!(id, 0);
788
+ /// assert_eq!(nodes.individual(id), Some(tskit::IndividualId::NULL));
789
+ /// assert_eq!(nodes.population(id), Some(tskit::PopulationId::NULL));
790
+ /// ```
791
+ ///
792
+ /// Use [struct update syntax](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)
793
+ /// to customize defaults:
794
+ ///
795
+ /// ```
796
+ /// # let mut nodes = tskit::NodeTable::default();
797
+ /// let defaults = tskit::NodeDefaults {
798
+ /// population: 3.into(),
799
+ /// ..Default::default()
800
+ /// };
801
+ /// let id = nodes.add_row_with_defaults(0.0, &defaults).unwrap();
802
+ /// # assert_eq!(id, 0);
803
+ /// # assert_eq!(nodes.individual(id), Some(tskit::IndividualId::NULL));
804
+ /// assert_eq!(nodes.population(id), Some(tskit::PopulationId::from(3)));
805
+ /// ```
806
+ ///
807
+ /// ## With metadata
808
+ ///
809
+ /// See the [book](https://tskit-dev.github.io/tskit-rust) for examples.
810
+ pub fn add_row_with_defaults < T : Into < Time > , D : DefaultNodeData > (
811
+ & mut self ,
812
+ time : T ,
813
+ defaults : & D ,
814
+ ) -> Result < NodeId , TskitError > {
815
+ let md = defaults. metadata ( ) ?;
816
+ let ( ptr, mdlen) = match & md {
817
+ Some ( value) => ( value. as_ptr ( ) , SizeType :: try_from ( value. len ( ) ) ?) ,
818
+ None => ( std:: ptr:: null ( ) , 0 . into ( ) ) ,
819
+ } ;
820
+ self . add_row_details (
821
+ defaults. flags ( ) ,
822
+ time,
823
+ defaults. population ( ) ,
824
+ defaults. individual ( ) ,
825
+ ptr. cast :: < i8 > ( ) ,
826
+ mdlen. into ( ) ,
827
+ )
828
+ }
829
+
523
830
build_table_column_slice_getter ! (
524
831
/// Get the time column as a slice
525
832
=> time, time_slice, Time ) ;
0 commit comments