@@ -4,6 +4,74 @@ mod experimental_features {
4
4
5
5
use tskit:: TableAccess ;
6
6
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
+
7
75
// Name is not great.
8
76
// We'd like to have this be : tskit::TableAccess,
9
77
// but that's a big ask at this stage.
@@ -22,6 +90,13 @@ mod experimental_features {
22
90
effect_size : f64 ,
23
91
}
24
92
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
+
25
100
// Goal:
26
101
//
27
102
// A table newtype can let us define tables in terms
@@ -57,6 +132,28 @@ mod experimental_features {
57
132
}
58
133
}
59
134
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
+
60
157
#[ test]
61
158
fn test_table_collection_newtype ( ) {
62
159
let mut tables = MyTableCollection ( tskit:: TableCollection :: new ( 1.0 ) . unwrap ( ) ) ;
@@ -67,6 +164,21 @@ mod experimental_features {
67
164
let decoded = tables. get_mutation_metadata ( 0 ) . unwrap ( ) . unwrap ( ) ;
68
165
assert_eq ! ( decoded. effect_size, 0.10 ) ;
69
166
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
+
70
182
// current API requires
71
183
let decoded = tables
72
184
. mutations ( )
0 commit comments