@@ -74,6 +74,7 @@ impl<'a> Iterator for EdgeTableIterator<'a> {
74
74
/// These are not created directly.
75
75
/// Instead, use [`TableAccess::edges`](crate::TableAccess::edges)
76
76
/// to get a reference to an existing edge table;
77
+ #[ repr( transparent) ]
77
78
pub struct EdgeTable < ' a > {
78
79
table_ : & ' a ll_bindings:: tsk_edge_table_t ,
79
80
}
@@ -167,3 +168,129 @@ impl<'a> EdgeTable<'a> {
167
168
table_row_access ! ( ri. 0 , self , make_edge_table_row)
168
169
}
169
170
}
171
+
172
+ /// A standalone edge table that owns its data.
173
+ ///
174
+ /// # Examples
175
+ ///
176
+ /// ```
177
+ /// use tskit::OwnedEdgeTable;
178
+ ///
179
+ /// let mut edges = OwnedEdgeTable::default();
180
+ /// let rowid = edges.add_row(1., 2., 0, 1).unwrap();
181
+ /// assert_eq!(rowid, 0);
182
+ /// assert_eq!(edges.num_rows(), 1);
183
+ /// ```
184
+ ///
185
+ /// An example with metadata.
186
+ /// This requires the cargo feature `"derive"` for `tskit`.
187
+ ///
188
+ /// ```
189
+ /// # #[cfg(any(feature="doc", feature="derive"))] {
190
+ /// use tskit::OwnedEdgeTable;
191
+ ///
192
+ /// #[derive(serde::Serialize,
193
+ /// serde::Deserialize,
194
+ /// tskit::metadata::EdgeMetadata)]
195
+ /// #[serializer("serde_json")]
196
+ /// struct EdgeMetadata {
197
+ /// value: i32,
198
+ /// }
199
+ ///
200
+ /// let metadata = EdgeMetadata{value: 42};
201
+ ///
202
+ /// let mut edges = OwnedEdgeTable::default();
203
+ ///
204
+ /// let rowid = edges.add_row_with_metadata(0., 1., 5, 10, &metadata).unwrap();
205
+ /// assert_eq!(rowid, 0);
206
+ ///
207
+ /// if let Some(decoded) = edges.metadata::<EdgeMetadata>(rowid).unwrap() {
208
+ /// assert_eq!(decoded.value, 42);
209
+ /// } else {
210
+ /// panic!("hmm...we expected some metadata!");
211
+ /// }
212
+ ///
213
+ /// # }
214
+ /// ```
215
+ pub struct OwnedEdgeTable {
216
+ table : mbox:: MBox < ll_bindings:: tsk_edge_table_t > ,
217
+ }
218
+
219
+ impl OwnedEdgeTable {
220
+ fn new ( ) -> Self {
221
+ let temp = unsafe {
222
+ libc:: malloc ( std:: mem:: size_of :: < ll_bindings:: tsk_edge_table_t > ( ) )
223
+ as * mut ll_bindings:: tsk_edge_table_t
224
+ } ;
225
+ let nonnull = match std:: ptr:: NonNull :: < ll_bindings:: tsk_edge_table_t > :: new ( temp) {
226
+ Some ( x) => x,
227
+ None => panic ! ( "out of memory" ) ,
228
+ } ;
229
+ let mut table = unsafe { mbox:: MBox :: from_non_null_raw ( nonnull) } ;
230
+ let rv = unsafe { ll_bindings:: tsk_edge_table_init ( & mut ( * table) , 0 ) } ;
231
+ assert_eq ! ( rv, 0 ) ;
232
+ Self { table }
233
+ }
234
+
235
+ pub fn add_row (
236
+ & mut self ,
237
+ left : impl Into < Position > ,
238
+ right : impl Into < Position > ,
239
+ parent : impl Into < NodeId > ,
240
+ child : impl Into < NodeId > ,
241
+ ) -> Result < EdgeId , TskitError > {
242
+ let rv = unsafe {
243
+ ll_bindings:: tsk_edge_table_add_row (
244
+ & mut ( * self . table ) ,
245
+ left. into ( ) . 0 ,
246
+ right. into ( ) . 0 ,
247
+ parent. into ( ) . 0 ,
248
+ child. into ( ) . 0 ,
249
+ std:: ptr:: null ( ) ,
250
+ 0 ,
251
+ )
252
+ } ;
253
+
254
+ handle_tsk_return_value ! ( rv, EdgeId :: from( rv) )
255
+ }
256
+
257
+ pub fn add_row_with_metadata < M : crate :: metadata:: EdgeMetadata > (
258
+ & mut self ,
259
+ left : impl Into < Position > ,
260
+ right : impl Into < Position > ,
261
+ parent : impl Into < NodeId > ,
262
+ child : impl Into < NodeId > ,
263
+ metadata : & M ,
264
+ ) -> Result < EdgeId , TskitError > {
265
+ let md = crate :: metadata:: EncodedMetadata :: new ( metadata) ?;
266
+ let rv = unsafe {
267
+ ll_bindings:: tsk_edge_table_add_row (
268
+ & mut ( * self . table ) ,
269
+ left. into ( ) . 0 ,
270
+ right. into ( ) . 0 ,
271
+ parent. into ( ) . 0 ,
272
+ child. into ( ) . 0 ,
273
+ md. as_ptr ( ) ,
274
+ md. len ( ) . into ( ) ,
275
+ )
276
+ } ;
277
+
278
+ handle_tsk_return_value ! ( rv, EdgeId :: from( rv) )
279
+ }
280
+ }
281
+
282
+ impl std:: ops:: Deref for OwnedEdgeTable {
283
+ type Target = EdgeTable < ' static > ;
284
+
285
+ fn deref ( & self ) -> & Self :: Target {
286
+ // SAFETY: that T* and &T have same layout,
287
+ // and Target is repr(transparent).
288
+ unsafe { std:: mem:: transmute ( & self . table ) }
289
+ }
290
+ }
291
+
292
+ impl Default for OwnedEdgeTable {
293
+ fn default ( ) -> Self {
294
+ Self :: new ( )
295
+ }
296
+ }
0 commit comments