|
| 1 | +//! Support for table row metadata |
| 2 | +
|
1 | 3 | use crate::bindings::{tsk_id_t, tsk_size_t}; |
2 | 4 | use thiserror::Error; |
3 | 5 |
|
| 6 | +/// Enable a type to be used as table metadata |
| 7 | +/// |
| 8 | +/// See [`handle_metadata_return`] for a macro to help implement this trait, |
| 9 | +/// and its use in examples below. |
| 10 | +/// |
| 11 | +/// We strongly recommend the use of the [serde](https://serde.rs/) ecosystem |
| 12 | +/// for row metadata. |
| 13 | +/// For many use cases, we imagine that |
| 14 | +/// [bincode](https://crates.io/crates/bincode) will be one of |
| 15 | +/// the more useful `serde`-related crates. |
| 16 | +/// |
| 17 | +/// # Examples |
| 18 | +/// |
| 19 | +/// ## Mutation metadata |
| 20 | +/// |
| 21 | +/// ``` |
| 22 | +/// use tskit::handle_metadata_return; |
| 23 | +/// use tskit::TableAccess; |
| 24 | +/// |
| 25 | +/// #[derive(serde::Serialize, serde::Deserialize)] |
| 26 | +/// pub struct MyMutation { |
| 27 | +/// origin_time: i32, |
| 28 | +/// effect_size: f64, |
| 29 | +/// dominance: f64, |
| 30 | +/// } |
| 31 | +/// |
| 32 | +/// impl tskit::metadata::MetadataRoundtrip for MyMutation { |
| 33 | +/// fn encode(&self) -> Result<Vec<u8>, tskit::metadata::MetadataError> { |
| 34 | +/// handle_metadata_return!(bincode::serialize(&self)) |
| 35 | +/// } |
| 36 | +/// |
| 37 | +/// fn decode(md: &[u8]) -> Result<Self, tskit::metadata::MetadataError> { |
| 38 | +/// handle_metadata_return!(bincode::deserialize(md)) |
| 39 | +/// } |
| 40 | +/// } |
| 41 | +/// |
| 42 | +/// let mut tables = tskit::TableCollection::new(100.).unwrap(); |
| 43 | +/// let mutation = MyMutation{origin_time: 100, |
| 44 | +/// effect_size: -1e-4, |
| 45 | +/// dominance: 0.25}; |
| 46 | +/// |
| 47 | +/// // Add table row with metadata. |
| 48 | +/// tables.add_mutation_with_metadata(0, 0, tskit::TSK_NULL, 100., None, |
| 49 | +/// Some(&mutation)).unwrap(); |
| 50 | +/// |
| 51 | +/// // Decode the metadata |
| 52 | +/// // The two unwraps are: |
| 53 | +/// // 1. Handle Errors vs Option. |
| 54 | +/// // 2. Handle the option for the case of no error. |
| 55 | +/// let decoded = tables.mutations().metadata::<MyMutation>(0).unwrap().unwrap(); |
| 56 | +/// assert_eq!(mutation.origin_time, decoded.origin_time); |
| 57 | +/// match decoded.effect_size.partial_cmp(&mutation.effect_size) { |
| 58 | +/// Some(std::cmp::Ordering::Greater) => assert!(false), |
| 59 | +/// Some(std::cmp::Ordering::Less) => assert!(false), |
| 60 | +/// Some(std::cmp::Ordering::Equal) => (), |
| 61 | +/// None => panic!("bad comparison"), |
| 62 | +/// }; |
| 63 | +/// match decoded.dominance.partial_cmp(&mutation.dominance) { |
| 64 | +/// Some(std::cmp::Ordering::Greater) => assert!(false), |
| 65 | +/// Some(std::cmp::Ordering::Less) => assert!(false), |
| 66 | +/// Some(std::cmp::Ordering::Equal) => (), |
| 67 | +/// None => panic!("bad comparison"), |
| 68 | +/// }; |
| 69 | +/// |
| 70 | +/// ``` |
4 | 71 | pub trait MetadataRoundtrip { |
5 | 72 | fn encode(&self) -> Result<Vec<u8>, MetadataError>; |
6 | 73 | fn decode(md: &[u8]) -> Result<Self, MetadataError> |
|
0 commit comments