@@ -14,67 +14,73 @@ use thiserror::Error;
1414/// [bincode](https://crates.io/crates/bincode) will be one of
1515/// the more useful `serde`-related crates.
1616///
17- /// # Examples
17+ /// The library provides two macros to facilitate implementing metadata
18+ /// traits:
1819///
19- /// ## Mutation metadata
20+ /// * [`serde_json_metadata`]
21+ /// * [`serde_bincode_metadata`]
2022///
21- /// ```
22- /// use tskit::handle_metadata_return;
23- /// use tskit::TableAccess;
23+ /// These macros are optional features.
24+ /// The feature names are the same as the macro names
2425///
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- /// impl tskit::metadata::MutationMetadata for MyMutation {}
43- ///
44- /// let mut tables = tskit::TableCollection::new(100.).unwrap();
45- /// let mutation = MyMutation{origin_time: 100,
46- /// effect_size: -1e-4,
47- /// dominance: 0.25};
48- ///
49- /// // Add table row with metadata.
50- /// tables.add_mutation_with_metadata(0, 0, tskit::MutationId::NULL, 100., None,
51- /// &mutation).unwrap();
52- ///
53- /// // Decode the metadata
54- /// // The two unwraps are:
55- /// // 1. Handle Errors vs Option.
56- /// // 2. Handle the option for the case of no error.
57- /// //
58- /// // The .into() reflects the fact that metadata fetching
59- /// // functions only take a strong ID type, and tskit-rust
60- /// // adds Into<strong ID type> for i32 for all strong ID types.
61- ///
62- /// let decoded = tables.mutations().metadata::<MyMutation>(0.into()).unwrap().unwrap();
63- /// assert_eq!(mutation.origin_time, decoded.origin_time);
64- /// match decoded.effect_size.partial_cmp(&mutation.effect_size) {
65- /// Some(std::cmp::Ordering::Greater) => assert!(false),
66- /// Some(std::cmp::Ordering::Less) => assert!(false),
67- /// Some(std::cmp::Ordering::Equal) => (),
68- /// None => panic!("bad comparison"),
69- /// };
70- /// match decoded.dominance.partial_cmp(&mutation.dominance) {
71- /// Some(std::cmp::Ordering::Greater) => assert!(false),
72- /// Some(std::cmp::Ordering::Less) => assert!(false),
73- /// Some(std::cmp::Ordering::Equal) => (),
74- /// None => panic!("bad comparison"),
75- /// };
76- ///
77- /// ```
26+ #[cfg_attr(
27+ feature = "provenance",
28+ doc = r##"
29+ # Examples
30+
31+ ## Mutation metadata encoded as JSON
32+
33+ ```
34+ use tskit::handle_metadata_return;
35+ use tskit::TableAccess;
36+
37+ #[derive(serde::Serialize, serde::Deserialize)]
38+ pub struct MyMutation {
39+ origin_time: i32,
40+ effect_size: f64,
41+ dominance: f64,
42+ }
43+
44+ // Implement tskit::metadata::MetadataRoundtrip
45+ tskit::serde_json_metadata!(MyMutation);
46+
47+ impl tskit::metadata::MutationMetadata for MyMutation {}
48+
49+ let mut tables = tskit::TableCollection::new(100.).unwrap();
50+ let mutation = MyMutation{origin_time: 100,
51+ effect_size: -1e-4,
52+ dominance: 0.25};
53+
54+ // Add table row with metadata.
55+ tables.add_mutation_with_metadata(0, 0, tskit::MutationId::NULL, 100., None,
56+ &mutation).unwrap();
57+
58+ // Decode the metadata
59+ // The two unwraps are:
60+ // 1. Handle Errors vs Option.
61+ // 2. Handle the option for the case of no error.
62+ //
63+ // The .into() reflects the fact that metadata fetching
64+ // functions only take a strong ID type, and tskit-rust
65+ // adds Into<strong ID type> for i32 for all strong ID types.
66+
67+ let decoded = tables.mutations().metadata::<MyMutation>(0.into()).unwrap().unwrap();
68+ assert_eq!(mutation.origin_time, decoded.origin_time);
69+ match decoded.effect_size.partial_cmp(&mutation.effect_size) {
70+ Some(std::cmp::Ordering::Greater) => assert!(false),
71+ Some(std::cmp::Ordering::Less) => assert!(false),
72+ Some(std::cmp::Ordering::Equal) => (),
73+ None => panic!("bad comparison"),
74+ };
75+ match decoded.dominance.partial_cmp(&mutation.dominance) {
76+ Some(std::cmp::Ordering::Greater) => assert!(false),
77+ Some(std::cmp::Ordering::Less) => assert!(false),
78+ Some(std::cmp::Ordering::Equal) => (),
79+ None => panic!("bad comparison"),
80+ };
81+ ```
82+ "##
83+ )]
7884pub trait MetadataRoundtrip {
7985 fn encode(&self) -> Result<Vec<u8>, MetadataError>;
8086 fn decode(md: &[u8]) -> Result<Self, MetadataError>
0 commit comments