@@ -4,6 +4,79 @@ mod experimental_features {
4
4
5
5
use tskit:: TableAccess ;
6
6
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
+
7
80
// Name is not great.
8
81
// We'd like to have this be : tskit::TableAccess,
9
82
// but that's a big ask at this stage.
@@ -22,6 +95,13 @@ mod experimental_features {
22
95
effect_size : f64 ,
23
96
}
24
97
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
+
25
105
// Goal:
26
106
//
27
107
// A table newtype can let us define tables in terms
@@ -57,6 +137,28 @@ mod experimental_features {
57
137
}
58
138
}
59
139
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
+
60
162
#[ test]
61
163
fn test_table_collection_newtype ( ) {
62
164
let mut tables = MyTableCollection ( tskit:: TableCollection :: new ( 1.0 ) . unwrap ( ) ) ;
@@ -67,6 +169,23 @@ mod experimental_features {
67
169
let decoded = tables. get_mutation_metadata ( 0 ) . unwrap ( ) . unwrap ( ) ;
68
170
assert_eq ! ( decoded. effect_size, 0.10 ) ;
69
171
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
+
70
189
// current API requires
71
190
let decoded = tables
72
191
. mutations ( )
0 commit comments