Skip to content

Commit a1aea5c

Browse files
committed
add examples of metadata round trips
1 parent 7352ca9 commit a1aea5c

File tree

5 files changed

+120
-2
lines changed

5 files changed

+120
-2
lines changed

.github/workflows/tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ jobs:
3333
override: true
3434
- run: cargo check
3535
- name: run tests
36-
run: cargo test
36+
run: |
37+
cargo test
38+
cargo test --examples
3739
3840
build-osx:
3941
runs-on: macos-latest
@@ -53,7 +55,9 @@ jobs:
5355
override: true
5456
- run: cargo check
5557
- name: run tests
56-
run: cargo test
58+
run: |
59+
cargo test
60+
cargo test --examples
5761
5862
fmt:
5963
name: rust fmt

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ repository = "https://github.com/molpopgen/tskit_rust"
1515
thiserror = "1.0"
1616
libc = "0.2.81"
1717

18+
[dev-dependencies]
19+
serde = {version = "1.0.118", features = ["derive"]}
20+
bincode = "1.3.1"
21+
1822
[build-dependencies]
1923
bindgen = "0.56.0"
2024
cc = { version = "1.0", features = ["parallel"] }

examples/mutation.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![macro_use]
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Serialize, Deserialize, Debug)]
5+
pub struct Mutation {
6+
pub effect_size: f64,
7+
pub dominance: f64,
8+
pub origin_time: i32,
9+
}
10+
11+
macro_rules! make_mutation_metadata_run {
12+
() => {
13+
pub fn run() {
14+
let mut tables = TableCollection::new(1000.).unwrap();
15+
// The simulation generates a mutation:
16+
let m = Mutation {
17+
effect_size: -0.235423,
18+
dominance: 0.5,
19+
origin_time: 1,
20+
};
21+
22+
// The mutation's data are included as metadata:
23+
tables
24+
.add_mutation_with_metadata(0, 0, 0, 0.0, None, Some(&m))
25+
.unwrap();
26+
27+
// Decoding requres 2 unwraps:
28+
// 1. The first is to handle errors.
29+
// 2. The second is b/c metadata are optional,
30+
// so a row may return None.
31+
let decoded = tables.mutations().metadata::<Mutation>(0).unwrap().unwrap();
32+
33+
// Check that we've made the round trip:
34+
assert_eq!(decoded.origin_time, 1);
35+
assert!((m.effect_size - decoded.effect_size).abs() < f64::EPSILON);
36+
assert!((m.dominance - decoded.dominance).abs() < f64::EPSILON);
37+
}
38+
};
39+
}
40+
41+
#[allow(dead_code)]
42+
fn main() {
43+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use tskit_rust::metadata;
2+
use tskit_rust::*;
3+
mod mutation;
4+
5+
use mutation::Mutation;
6+
7+
impl metadata::MetadataRoundtrip for Mutation {
8+
fn encode(&self) -> Result<Vec<u8>, metadata::MetadataError> {
9+
let mut rv = vec![];
10+
rv.extend(self.effect_size.to_le_bytes().iter().copied());
11+
rv.extend(self.dominance.to_le_bytes().iter().copied());
12+
rv.extend(self.origin_time.to_le_bytes().iter().copied());
13+
Ok(rv)
14+
}
15+
16+
fn decode(md: &[u8]) -> Result<Self, metadata::MetadataError> {
17+
use std::convert::TryInto;
18+
let (effect_size_bytes, rest) = md.split_at(std::mem::size_of::<f64>());
19+
let (dominance_bytes, rest) = rest.split_at(std::mem::size_of::<f64>());
20+
let (origin_time_bytes, _) = rest.split_at(std::mem::size_of::<i32>());
21+
Ok(Self {
22+
effect_size: f64::from_le_bytes(effect_size_bytes.try_into().unwrap()),
23+
dominance: f64::from_le_bytes(dominance_bytes.try_into().unwrap()),
24+
origin_time: i32::from_le_bytes(origin_time_bytes.try_into().unwrap()),
25+
})
26+
}
27+
}
28+
29+
make_mutation_metadata_run!();
30+
31+
#[test]
32+
fn run_bincode() {
33+
run();
34+
}
35+
36+
fn main() {
37+
run();
38+
}

examples/mutation_metadata_std.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use tskit_rust::metadata;
2+
use tskit_rust::*;
3+
mod mutation;
4+
5+
use mutation::Mutation;
6+
7+
// Implement the metadata trait for our mutation
8+
// type. Will will use the standard library for the implementation
9+
// details.
10+
impl metadata::MetadataRoundtrip for Mutation {
11+
fn encode(&self) -> Result<Vec<u8>, metadata::MetadataError> {
12+
Ok(bincode::serialize(&self).unwrap())
13+
}
14+
15+
fn decode(md: &[u8]) -> Result<Self, metadata::MetadataError> {
16+
Ok(bincode::deserialize(md).unwrap())
17+
}
18+
}
19+
20+
make_mutation_metadata_run!();
21+
22+
#[test]
23+
fn run_std() {
24+
run();
25+
}
26+
27+
fn main() {
28+
run();
29+
}

0 commit comments

Comments
 (0)