Skip to content

Commit 03a06c6

Browse files
committed
test: Add another experimental trait idea for metadata.
1 parent d22e716 commit 03a06c6

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

tests/experimental.rs

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

55
use tskit::TableAccess;
66

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

93+
#[derive(serde::Serialize, serde::Deserialize, tskit::metadata::MutationMetadata)]
94+
#[serializer("serde_json")]
95+
struct IndividualMetadataType {
96+
fitness: f64,
97+
location: [f64; 3],
98+
}
99+
25100
// Goal:
26101
//
27102
// A table newtype can let us define tables in terms
@@ -57,6 +132,28 @@ mod experimental_features {
57132
}
58133
}
59134

135+
impl MetadataRetrieval<tskit::MutationId> for MyTableCollection {
136+
type Metadata = MutationMetadataType;
137+
fn retrieve(
138+
&self,
139+
row: impl Into<tskit::MutationId>,
140+
) -> Result<Option<MutationMetadataType>, tskit::TskitError> {
141+
self.mutations()
142+
.metadata::<MutationMetadataType>(row.into())
143+
}
144+
}
145+
146+
impl MetadataRetrieval<tskit::IndividualId> for MyTableCollection {
147+
type Metadata = IndividualMetadataType;
148+
fn retrieve(
149+
&self,
150+
row: impl Into<tskit::MutationId>,
151+
) -> Result<Option<MutationMetadataType>, tskit::TskitError> {
152+
self.individuals()
153+
.metadata::<IndividualMetadataType>(row.into())
154+
}
155+
}
156+
60157
#[test]
61158
fn test_table_collection_newtype() {
62159
let mut tables = MyTableCollection(tskit::TableCollection::new(1.0).unwrap());
@@ -67,6 +164,21 @@ mod experimental_features {
67164
let decoded = tables.get_mutation_metadata(0).unwrap().unwrap();
68165
assert_eq!(decoded.effect_size, 0.10);
69166

167+
// More ergonomic here...
168+
let decoded = tables.retrieve(0).unwrap().unwrap();
169+
assert_eq!(decoded.effect_size, 0.10);
170+
171+
// ...but not here, which is how it would normally be called...
172+
let decoded =
173+
<MyTableCollection as MetadataRetrieval<tskit::MutationId>>::retrieve(&tables, 0)
174+
.unwrap()
175+
.unwrap();
176+
assert_eq!(decoded.effect_size, 0.10);
177+
178+
// ... but blanket impl may be a path to glory.
179+
let decoded = tables.mutation_metadata(0).unwrap().unwrap();
180+
assert_eq!(decoded.effect_size, 0.10);
181+
70182
// current API requires
71183
let decoded = tables
72184
.mutations()

0 commit comments

Comments
 (0)