Skip to content

Commit 3a4f14b

Browse files
authored
test: Add another experimental trait idea for metadata. (#261)
1 parent d22e716 commit 3a4f14b

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

tests/experimental.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,79 @@ mod experimental_features {
44

55
use tskit::TableAccess;
66

7+
// Goal: proc macro this up
8+
// Design notes for future:
9+
// * We can probably drop this trait.
10+
// * We want a derive macro based on XMetadataRetrieval,
11+
// where X is a table type.
12+
// * So hopefully we can start there.
13+
trait MetadataRetrieval<R> {
14+
type Metadata: tskit::metadata::MetadataRoundtrip;
15+
fn metadata(&self, r: impl Into<R>) -> Result<Option<Self::Metadata>, tskit::TskitError>;
16+
}
17+
18+
// Specific traits cover the various row id types
19+
trait MutationMetadataRetrieval: MetadataRetrieval<tskit::MutationId> {
20+
fn mutation_metadata(
21+
&self,
22+
row: impl Into<tskit::MutationId>,
23+
) -> Result<
24+
Option<<Self as MetadataRetrieval<tskit::MutationId>>::Metadata>,
25+
tskit::TskitError,
26+
>
27+
where
28+
<Self as MetadataRetrieval<tskit::MutationId>>::Metadata:
29+
tskit::metadata::MutationMetadata;
30+
}
31+
32+
// Blanket implementations are possible given the above
33+
// two defnitions, putting all boiler plate out of sight!
34+
impl<T> MutationMetadataRetrieval for T
35+
where
36+
T: MetadataRetrieval<tskit::MutationId>,
37+
<Self as MetadataRetrieval<tskit::MutationId>>::Metadata: tskit::metadata::MutationMetadata,
38+
{
39+
fn mutation_metadata(
40+
&self,
41+
row: impl Into<tskit::MutationId>,
42+
) -> Result<
43+
Option<<Self as MetadataRetrieval<tskit::MutationId>>::Metadata>,
44+
tskit::TskitError,
45+
> {
46+
self.metadata(row)
47+
}
48+
}
49+
50+
trait IndividualMetadataRetrieval: MetadataRetrieval<tskit::IndividualId> {
51+
fn individual_metadata(
52+
&self,
53+
row: impl Into<tskit::IndividualId>,
54+
) -> Result<
55+
Option<<Self as MetadataRetrieval<tskit::IndividualId>>::Metadata>,
56+
tskit::TskitError,
57+
>
58+
where
59+
<Self as MetadataRetrieval<tskit::IndividualId>>::Metadata:
60+
tskit::metadata::MutationMetadata;
61+
}
62+
63+
impl<T> IndividualMetadataRetrieval for T
64+
where
65+
T: MetadataRetrieval<tskit::IndividualId>,
66+
<Self as MetadataRetrieval<tskit::IndividualId>>::Metadata:
67+
tskit::metadata::IndividualMetadata,
68+
{
69+
fn individual_metadata(
70+
&self,
71+
row: impl Into<tskit::IndividualId>,
72+
) -> Result<
73+
Option<<Self as MetadataRetrieval<tskit::IndividualId>>::Metadata>,
74+
tskit::TskitError,
75+
> {
76+
self.metadata(row)
77+
}
78+
}
79+
780
// Name is not great.
881
// We'd like to have this be : tskit::TableAccess,
982
// but that's a big ask at this stage.
@@ -22,6 +95,13 @@ mod experimental_features {
2295
effect_size: f64,
2396
}
2497

98+
#[derive(serde::Serialize, serde::Deserialize, tskit::metadata::IndividualMetadata)]
99+
#[serializer("serde_json")]
100+
struct IndividualMetadataType {
101+
fitness: f64,
102+
location: [f64; 3],
103+
}
104+
25105
// Goal:
26106
//
27107
// A table newtype can let us define tables in terms
@@ -57,6 +137,28 @@ mod experimental_features {
57137
}
58138
}
59139

140+
impl MetadataRetrieval<tskit::MutationId> for MyTableCollection {
141+
type Metadata = MutationMetadataType;
142+
fn metadata(
143+
&self,
144+
row: impl Into<tskit::MutationId>,
145+
) -> Result<Option<MutationMetadataType>, tskit::TskitError> {
146+
self.mutations()
147+
.metadata::<MutationMetadataType>(row.into())
148+
}
149+
}
150+
151+
impl MetadataRetrieval<tskit::IndividualId> for MyTableCollection {
152+
type Metadata = IndividualMetadataType;
153+
fn metadata(
154+
&self,
155+
row: impl Into<tskit::IndividualId>,
156+
) -> Result<Option<IndividualMetadataType>, tskit::TskitError> {
157+
self.individuals()
158+
.metadata::<IndividualMetadataType>(row.into())
159+
}
160+
}
161+
60162
#[test]
61163
fn test_table_collection_newtype() {
62164
let mut tables = MyTableCollection(tskit::TableCollection::new(1.0).unwrap());
@@ -67,6 +169,23 @@ mod experimental_features {
67169
let decoded = tables.get_mutation_metadata(0).unwrap().unwrap();
68170
assert_eq!(decoded.effect_size, 0.10);
69171

172+
// More ergonomic here...
173+
// NOTE: this can no longer compile b/c we've
174+
// got the pattern in place for > 1 trait.
175+
// let decoded = tables.metadata(0).unwrap().unwrap();
176+
// assert_eq!(decoded.effect_size, 0.10);
177+
178+
// ...but not here, which is how it would normally be called...
179+
let decoded =
180+
<MyTableCollection as MetadataRetrieval<tskit::MutationId>>::metadata(&tables, 0)
181+
.unwrap()
182+
.unwrap();
183+
assert_eq!(decoded.effect_size, 0.10);
184+
185+
// ... but blanket impl may be a path to glory.
186+
let decoded = tables.mutation_metadata(0).unwrap().unwrap();
187+
assert_eq!(decoded.effect_size, 0.10);
188+
70189
// current API requires
71190
let decoded = tables
72191
.mutations()

0 commit comments

Comments
 (0)