|
83 | 83 | )
|
84 | 84 | }
|
85 | 85 |
|
| 86 | +pub(crate) fn add_row_with_defaults<T: Into<crate::Time>, D: crate::node_table::DefaultNodeData>( |
| 87 | + time: T, |
| 88 | + defaults: &D, |
| 89 | + table: *mut ll_bindings::tsk_node_table_t, |
| 90 | +) -> Result<NodeId, TskitError> { |
| 91 | + let md = defaults.metadata()?; |
| 92 | + let (ptr, mdlen) = match &md { |
| 93 | + Some(value) => ( |
| 94 | + value.as_ptr().cast::<i8>(), |
| 95 | + crate::SizeType::try_from(value.len())?, |
| 96 | + ), |
| 97 | + None => (std::ptr::null(), 0.into()), |
| 98 | + }; |
| 99 | + add_row_details( |
| 100 | + defaults.flags().bits(), |
| 101 | + time.into().into(), |
| 102 | + defaults.population().into(), |
| 103 | + defaults.individual().into(), |
| 104 | + ptr, |
| 105 | + mdlen.into(), |
| 106 | + table, |
| 107 | + ) |
| 108 | +} |
| 109 | + |
86 | 110 | /// Row of a [`NodeTable`]
|
87 | 111 | #[derive(Debug)]
|
88 | 112 | pub struct NodeTableRow {
|
@@ -214,6 +238,243 @@ impl<'a> streaming_iterator::StreamingIterator for NodeTableRowView<'a> {
|
214 | 238 | }
|
215 | 239 | }
|
216 | 240 |
|
| 241 | +/// Defaults for node table rows without metadata |
| 242 | +/// |
| 243 | +/// # Examples |
| 244 | +/// |
| 245 | +/// ``` |
| 246 | +/// let d = tskit::NodeDefaults::default(); |
| 247 | +/// assert_eq!(d.flags, tskit::NodeFlags::default()); |
| 248 | +/// assert_eq!(d.population, tskit::PopulationId::NULL); |
| 249 | +/// assert_eq!(d.individual, tskit::IndividualId::NULL); |
| 250 | +/// ``` |
| 251 | +/// |
| 252 | +/// [Struct update syntax](https://doc.rust-lang.org/book/ch05-01-defining-structs.html) |
| 253 | +/// is your friend here: |
| 254 | +/// |
| 255 | +/// ``` |
| 256 | +/// let d = tskit::NodeDefaults{population: 0.into(), ..Default::default()}; |
| 257 | +/// assert_eq!(d.flags, tskit::NodeFlags::default()); |
| 258 | +/// assert_eq!(d.population, 0); |
| 259 | +/// assert_eq!(d.individual, tskit::IndividualId::NULL); |
| 260 | +/// let d2 = tskit::NodeDefaults{flags: tskit::NodeFlags::default().mark_sample(), |
| 261 | +/// // update remaining values from d |
| 262 | +/// ..d}; |
| 263 | +/// assert!(d2.flags.is_sample()); |
| 264 | +/// assert_eq!(d2.population, 0); |
| 265 | +/// assert_eq!(d2.individual, tskit::IndividualId::NULL); |
| 266 | +/// ``` |
| 267 | +#[derive(Copy, Clone, Default, Eq, PartialEq, Debug)] |
| 268 | +pub struct NodeDefaults { |
| 269 | + pub flags: NodeFlags, |
| 270 | + pub population: PopulationId, |
| 271 | + pub individual: IndividualId, |
| 272 | +} |
| 273 | + |
| 274 | +// Defaults for node table rows with metadata |
| 275 | +/// |
| 276 | +/// # Notes |
| 277 | +/// |
| 278 | +/// This struct derives `Debug` and `Clone`. |
| 279 | +/// However, neither is a trait bound on `M`. |
| 280 | +/// Therefore, use of `Debug` and/or `Clone` will fail unless `M` |
| 281 | +/// also implements the relevant trait. |
| 282 | +/// |
| 283 | +/// See [the book](https://tskit-dev.github.io/tskit-rust/) |
| 284 | +/// for details. |
| 285 | +#[derive(Debug, Clone, Default)] |
| 286 | +pub struct NodeDefaultsWithMetadata<M> |
| 287 | +where |
| 288 | + M: crate::metadata::NodeMetadata, |
| 289 | +{ |
| 290 | + pub flags: NodeFlags, |
| 291 | + pub population: PopulationId, |
| 292 | + pub individual: IndividualId, |
| 293 | + pub metadata: Option<M>, |
| 294 | +} |
| 295 | + |
| 296 | +mod private { |
| 297 | + pub trait DefaultNodeDataMarker {} |
| 298 | + |
| 299 | + impl DefaultNodeDataMarker for super::NodeDefaults {} |
| 300 | + |
| 301 | + impl<M> DefaultNodeDataMarker for super::NodeDefaultsWithMetadata<M> where |
| 302 | + M: crate::metadata::NodeMetadata |
| 303 | + { |
| 304 | + } |
| 305 | +} |
| 306 | + |
| 307 | +/// This trait is sealed. |
| 308 | +pub trait DefaultNodeData: private::DefaultNodeDataMarker { |
| 309 | + fn flags(&self) -> NodeFlags; |
| 310 | + fn population(&self) -> PopulationId; |
| 311 | + fn individual(&self) -> IndividualId; |
| 312 | + fn metadata(&self) -> Result<Option<Vec<u8>>, TskitError>; |
| 313 | +} |
| 314 | + |
| 315 | +impl DefaultNodeData for NodeDefaults { |
| 316 | + fn flags(&self) -> NodeFlags { |
| 317 | + self.flags |
| 318 | + } |
| 319 | + fn population(&self) -> PopulationId { |
| 320 | + self.population |
| 321 | + } |
| 322 | + fn individual(&self) -> IndividualId { |
| 323 | + self.individual |
| 324 | + } |
| 325 | + fn metadata(&self) -> Result<Option<Vec<u8>>, TskitError> { |
| 326 | + Ok(None) |
| 327 | + } |
| 328 | +} |
| 329 | + |
| 330 | +impl<M> DefaultNodeData for NodeDefaultsWithMetadata<M> |
| 331 | +where |
| 332 | + M: crate::metadata::NodeMetadata, |
| 333 | +{ |
| 334 | + fn flags(&self) -> NodeFlags { |
| 335 | + self.flags |
| 336 | + } |
| 337 | + fn population(&self) -> PopulationId { |
| 338 | + self.population |
| 339 | + } |
| 340 | + fn individual(&self) -> IndividualId { |
| 341 | + self.individual |
| 342 | + } |
| 343 | + fn metadata(&self) -> Result<Option<Vec<u8>>, TskitError> { |
| 344 | + self.metadata.as_ref().map_or_else( |
| 345 | + || Ok(None), |
| 346 | + |v| match v.encode() { |
| 347 | + Ok(x) => Ok(Some(x)), |
| 348 | + Err(e) => Err(e.into()), |
| 349 | + }, |
| 350 | + ) |
| 351 | + } |
| 352 | +} |
| 353 | + |
| 354 | +/// This is a doctest hack as described in the rust book. |
| 355 | +/// We do this b/c the specific error messages can change |
| 356 | +/// across rust versions, making crates like trybuild |
| 357 | +/// less useful. |
| 358 | +/// |
| 359 | +/// ```compile_fail |
| 360 | +/// #[derive(serde::Serialize, serde::Deserialize)] |
| 361 | +/// struct NodeMetadata { |
| 362 | +/// value: i32, |
| 363 | +/// } |
| 364 | +/// |
| 365 | +/// impl Default for NodeMetadata { |
| 366 | +/// fn default() -> Self { |
| 367 | +/// Self{value: 0} |
| 368 | +/// } |
| 369 | +/// } |
| 370 | +/// |
| 371 | +/// impl tskit::metadata::MetadataRoundtrip for NodeMetadata { |
| 372 | +/// fn encode(&self) -> Result<Vec<u8>, tskit::metadata::MetadataError> { |
| 373 | +/// match serde_json::to_string(self) { |
| 374 | +/// Ok(x) => Ok(x.as_bytes().to_vec()), |
| 375 | +/// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }), |
| 376 | +/// } |
| 377 | +/// } |
| 378 | +/// fn decode(md: &[u8]) -> Result<Self, tskit::metadata::MetadataError> |
| 379 | +/// where |
| 380 | +/// Self: Sized, |
| 381 | +/// { |
| 382 | +/// match serde_json::from_slice(md) { |
| 383 | +/// Ok(v) => Ok(v), |
| 384 | +/// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }), |
| 385 | +/// } |
| 386 | +/// } |
| 387 | +/// } |
| 388 | +/// |
| 389 | +/// impl tskit::metadata::NodeMetadata for NodeMetadata {} |
| 390 | +/// |
| 391 | +/// type DefaultsWithMetadata = tskit::NodeDefaultsWithMetadata<NodeMetadata>; |
| 392 | +/// let defaults = DefaultsWithMetadata { |
| 393 | +/// metadata: Some(NodeMetadata { value: 42 }), |
| 394 | +/// ..Default::default() |
| 395 | +/// }; |
| 396 | +/// |
| 397 | +/// // Fails because metadata type is not Debug |
| 398 | +/// println!("{:?}", defaults); |
| 399 | +/// ``` |
| 400 | +/// |
| 401 | +/// ```compile_fail |
| 402 | +/// #[derive(serde::Serialize, serde::Deserialize)] |
| 403 | +/// struct NodeMetadata { |
| 404 | +/// value: i32, |
| 405 | +/// } |
| 406 | +/// |
| 407 | +/// impl Default for NodeMetadata { |
| 408 | +/// fn default() -> Self { |
| 409 | +/// Self{value: 0} |
| 410 | +/// } |
| 411 | +/// } |
| 412 | +/// |
| 413 | +/// impl tskit::metadata::MetadataRoundtrip for NodeMetadata { |
| 414 | +/// fn encode(&self) -> Result<Vec<u8>, tskit::metadata::MetadataError> { |
| 415 | +/// match serde_json::to_string(self) { |
| 416 | +/// Ok(x) => Ok(x.as_bytes().to_vec()), |
| 417 | +/// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }), |
| 418 | +/// } |
| 419 | +/// } |
| 420 | +/// fn decode(md: &[u8]) -> Result<Self, tskit::metadata::MetadataError> |
| 421 | +/// where |
| 422 | +/// Self: Sized, |
| 423 | +/// { |
| 424 | +/// match serde_json::from_slice(md) { |
| 425 | +/// Ok(v) => Ok(v), |
| 426 | +/// Err(e) => Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) }), |
| 427 | +/// } |
| 428 | +/// } |
| 429 | +/// } |
| 430 | +/// |
| 431 | +/// impl tskit::metadata::NodeMetadata for NodeMetadata {} |
| 432 | +/// |
| 433 | +/// let mut tables = tskit::TableCollection::new(10.0).unwrap(); |
| 434 | +/// type DefaultsWithMetadata = tskit::NodeDefaultsWithMetadata<NodeMetadata>; |
| 435 | +/// // What if there is default metadata for all rows? |
| 436 | +/// let defaults = DefaultsWithMetadata { |
| 437 | +/// metadata: Some(NodeMetadata { value: 42 }), |
| 438 | +/// ..Default::default() |
| 439 | +/// }; |
| 440 | +/// // We can scoop all non-metadata fields even though |
| 441 | +/// // type is not Copy/Clone |
| 442 | +/// let _ = tables |
| 443 | +/// .add_node_with_defaults( |
| 444 | +/// 0.0, |
| 445 | +/// &DefaultsWithMetadata { |
| 446 | +/// metadata: Some(NodeMetadata { value: 2 * 42 }), |
| 447 | +/// ..defaults |
| 448 | +/// }, |
| 449 | +/// ) |
| 450 | +/// .unwrap(); |
| 451 | +/// // But now, we start to cause a problem: |
| 452 | +/// // If we don't clone here, our metadata type moves, |
| 453 | +/// // so our defaults are moved. |
| 454 | +/// let _ = tables |
| 455 | +/// .add_node_with_defaults( |
| 456 | +/// 0.0, |
| 457 | +/// &DefaultsWithMetadata { |
| 458 | +/// population: 6.into(), |
| 459 | +/// ..defaults |
| 460 | +/// }, |
| 461 | +/// ) |
| 462 | +/// .unwrap(); |
| 463 | +/// // Now, we have a use-after-move error |
| 464 | +/// // if we hadn't cloned in the last step. |
| 465 | +/// let _ = tables |
| 466 | +/// .add_node_with_defaults( |
| 467 | +/// 0.0, |
| 468 | +/// &DefaultsWithMetadata { |
| 469 | +/// individual: 7.into(), |
| 470 | +/// ..defaults |
| 471 | +/// }, |
| 472 | +/// ) |
| 473 | +/// .unwrap(); |
| 474 | +/// ``` |
| 475 | +#[cfg(doctest)] |
| 476 | +struct NodeDefaultsWithMetadataNotCloneNotDebug; |
| 477 | + |
217 | 478 | /// An immtable view of a node table.
|
218 | 479 | #[derive(Debug)]
|
219 | 480 | #[repr(transparent)]
|
@@ -700,6 +961,26 @@ impl OwningNodeTable {
|
700 | 961 | self.as_mut_ptr(),
|
701 | 962 | )
|
702 | 963 | }
|
| 964 | + |
| 965 | + /// Add row with defaults |
| 966 | + /// |
| 967 | + /// # Examples |
| 968 | + /// |
| 969 | + /// ``` |
| 970 | + /// # let mut nodes = tskit::OwningNodeTable::default(); |
| 971 | + /// let node_defaults = tskit::NodeDefaults::default(); |
| 972 | + /// let rv = nodes.add_row_with_defaults(1.0, &node_defaults).unwrap(); |
| 973 | + /// assert_eq!(rv, 0); |
| 974 | + /// let rv = nodes.add_row_with_defaults(1.0, &node_defaults).unwrap(); |
| 975 | + /// assert_eq!(rv, 1); |
| 976 | + /// ``` |
| 977 | + pub fn add_row_with_defaults<T: Into<crate::Time> + Copy, D: DefaultNodeData>( |
| 978 | + &mut self, |
| 979 | + time: T, |
| 980 | + defaults: &D, |
| 981 | + ) -> Result<NodeId, TskitError> { |
| 982 | + add_row_with_defaults(time, defaults, self.as_mut_ptr()) |
| 983 | + } |
703 | 984 | }
|
704 | 985 |
|
705 | 986 | #[cfg(test)]
|
|
0 commit comments