@@ -119,3 +119,111 @@ impl_individual_parents!(
119
119
) ;
120
120
impl_individual_parents ! ( N , usize , & [ crate :: IndividualId ; N ] , self , self . as_slice( ) ) ;
121
121
impl_individual_parents ! ( N , usize , [ crate :: IndividualId ; N ] , self , self . as_slice( ) ) ;
122
+
123
+ mod private {
124
+ pub trait NewTypeMarker : TryInto < usize , Error = crate :: TskitError > { }
125
+ pub trait TableColumnMarker { }
126
+ }
127
+
128
+ impl private:: NewTypeMarker for crate :: EdgeId { }
129
+ impl private:: NewTypeMarker for crate :: NodeId { }
130
+ impl private:: NewTypeMarker for crate :: SiteId { }
131
+ impl private:: NewTypeMarker for crate :: MutationId { }
132
+ impl private:: NewTypeMarker for crate :: MigrationId { }
133
+ impl private:: NewTypeMarker for crate :: IndividualId { }
134
+ impl private:: NewTypeMarker for crate :: PopulationId { }
135
+ #[ cfg( feature = "provenance" ) ]
136
+ #[ cfg_attr( doc_cfg, doc( cfg( feature = "provenance" ) ) ) ]
137
+ impl private:: NewTypeMarker for crate :: ProvenanceId { }
138
+
139
+ /// Interface of a non-ragged table column.
140
+ ///
141
+ /// Unlike slice views of table columns, this API
142
+ /// allows indexed via row id types and [`crate::SizeType`].
143
+ ///
144
+ /// # Notes
145
+ ///
146
+ /// * This trait is sealed.
147
+ ///
148
+ /// # For C programmers
149
+ ///
150
+ /// The `C` programming language allows implicit casts between
151
+ /// integer types.
152
+ /// This implicit behavior allows one to index a table column
153
+ /// using a row id type ([`crate::bindings::tsk_id_t`]) because
154
+ /// the compiler will cast it to `size_t`.
155
+ ///
156
+ /// `rust` does not allow implicit casts, which makes working
157
+ /// with table columns as slices awkward.
158
+ /// One has to manually cast the id type and the resulting code isn't
159
+ /// nice to read.
160
+ ///
161
+ /// This trait solves that problem by requiring that [`std::ops::Index`]
162
+ /// by implemented for types that one would like to use as indexes
163
+ /// in the `tskit` world.
164
+ pub trait TableColumn < I , T > :
165
+ std:: ops:: Index < I , Output = T >
166
+ + std:: ops:: Index < usize , Output = T >
167
+ + std:: ops:: Index < crate :: SizeType , Output = T >
168
+ + private:: TableColumnMarker
169
+ {
170
+ /// Get the underlying slice
171
+ fn as_slice ( & self ) -> & [ T ] ;
172
+
173
+ /// Get with a table row identifier such as [`crate::NodeId`]
174
+ fn get_with_id ( & self , at : I ) -> Option < & T > ;
175
+
176
+ /// The "standard" get function
177
+ fn get ( & self , at : usize ) -> Option < & T > {
178
+ self . as_slice ( ) . get ( at)
179
+ }
180
+
181
+ /// Get with [`crate::SizeType`]
182
+ fn get_with_size_type ( & self , at : crate :: SizeType ) -> Option < & T > {
183
+ self . as_slice ( ) . get ( usize:: try_from ( at) . ok ( ) ?)
184
+ }
185
+
186
+ /// Iterator over the data.
187
+ fn iter < ' a , ' b > ( & ' a self ) -> impl Iterator < Item = & ' b T >
188
+ where
189
+ ' a : ' b ,
190
+ T : ' b ,
191
+ {
192
+ self . as_slice ( ) . iter ( )
193
+ }
194
+
195
+ /// Column length
196
+ fn len ( & self ) -> usize {
197
+ self . as_slice ( ) . len ( )
198
+ }
199
+
200
+ /// Query if column is empty
201
+ fn is_empty ( & self ) -> bool {
202
+ self . as_slice ( ) . is_empty ( )
203
+ }
204
+ }
205
+
206
+ impl < T > private:: TableColumnMarker for crate :: table_column:: OpaqueTableColumn < ' _ , T > { }
207
+
208
+ impl < I , T > std:: ops:: Index < I > for crate :: table_column:: OpaqueTableColumn < ' _ , T >
209
+ where
210
+ I : private:: NewTypeMarker ,
211
+ {
212
+ type Output = T ;
213
+ fn index ( & self , index : I ) -> & Self :: Output {
214
+ & self . 0 [ index. try_into ( ) . unwrap ( ) ]
215
+ }
216
+ }
217
+
218
+ impl < I , T > TableColumn < I , T > for crate :: table_column:: OpaqueTableColumn < ' _ , T >
219
+ where
220
+ I : private:: NewTypeMarker ,
221
+ {
222
+ fn as_slice ( & self ) -> & [ T ] {
223
+ self . 0
224
+ }
225
+
226
+ fn get_with_id ( & self , at : I ) -> Option < & T > {
227
+ self . 0 . get ( at. try_into ( ) . ok ( ) ?)
228
+ }
229
+ }
0 commit comments