@@ -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