@@ -65,6 +65,7 @@ impl<'a> Iterator for PopulationTableIterator<'a> {
65
65
/// These are not created directly.
66
66
/// Instead, use [`TableAccess::populations`](crate::TableAccess::populations)
67
67
/// to get a reference to an existing population table;
68
+ #[ repr( transparent) ]
68
69
pub struct PopulationTable < ' a > {
69
70
table_ : & ' a ll_bindings:: tsk_population_table_t ,
70
71
}
@@ -114,3 +115,105 @@ impl<'a> PopulationTable<'a> {
114
115
table_row_access ! ( ri. 0 , self , make_population_table_row)
115
116
}
116
117
}
118
+
119
+ /// A standalone population table that owns its data.
120
+ ///
121
+ /// # Examples
122
+ ///
123
+ /// ```
124
+ /// use tskit::OwnedPopulationTable;
125
+ ///
126
+ /// let mut populations = OwnedPopulationTable::default();
127
+ /// let rowid = populations.add_row().unwrap();
128
+ /// assert_eq!(rowid, 0);
129
+ /// assert_eq!(populations.num_rows(), 1);
130
+ /// ```
131
+ ///
132
+ /// An example with metadata.
133
+ /// This requires the cargo feature `"derive"` for `tskit`.
134
+ ///
135
+ /// ```
136
+ /// # #[cfg(any(feature="doc", feature="derive"))] {
137
+ /// use tskit::OwnedPopulationTable;
138
+ ///
139
+ /// #[derive(serde::Serialize,
140
+ /// serde::Deserialize,
141
+ /// tskit::metadata::PopulationMetadata)]
142
+ /// #[serializer("serde_json")]
143
+ /// struct PopulationMetadata {
144
+ /// name: String,
145
+ /// }
146
+ ///
147
+ /// let metadata = PopulationMetadata{name: "YRB".to_string()};
148
+ ///
149
+ /// let mut populations = OwnedPopulationTable::default();
150
+ ///
151
+ /// let rowid = populations.add_row_with_metadata(&metadata).unwrap();
152
+ /// assert_eq!(rowid, 0);
153
+ ///
154
+ /// if let Some(decoded) = populations.metadata::<PopulationMetadata>(rowid).unwrap() {
155
+ /// assert_eq!(&decoded.name, "YRB");
156
+ /// } else {
157
+ /// panic!("hmm...we expected some metadata!");
158
+ /// }
159
+ ///
160
+ /// # }
161
+ /// ```
162
+ pub struct OwnedPopulationTable {
163
+ table : mbox:: MBox < ll_bindings:: tsk_population_table_t > ,
164
+ }
165
+
166
+ impl OwnedPopulationTable {
167
+ fn new ( ) -> Self {
168
+ let temp = unsafe {
169
+ libc:: malloc ( std:: mem:: size_of :: < ll_bindings:: tsk_population_table_t > ( ) )
170
+ as * mut ll_bindings:: tsk_population_table_t
171
+ } ;
172
+ let nonnull = match std:: ptr:: NonNull :: < ll_bindings:: tsk_population_table_t > :: new ( temp) {
173
+ Some ( x) => x,
174
+ None => panic ! ( "out of memory" ) ,
175
+ } ;
176
+ let table = unsafe { mbox:: MBox :: from_non_null_raw ( nonnull) } ;
177
+ Self { table }
178
+ }
179
+
180
+ pub fn add_row ( & mut self ) -> Result < PopulationId , TskitError > {
181
+ let rv = unsafe {
182
+ ll_bindings:: tsk_population_table_add_row ( & mut ( * self . table ) , std:: ptr:: null ( ) , 0 )
183
+ } ;
184
+
185
+ handle_tsk_return_value ! ( rv, PopulationId :: from( rv) )
186
+ }
187
+
188
+ pub fn add_row_with_metadata < M : crate :: metadata:: PopulationMetadata > (
189
+ & mut self ,
190
+ metadata : & M ,
191
+ ) -> Result < PopulationId , TskitError > {
192
+ let md = crate :: metadata:: EncodedMetadata :: new ( metadata) ?;
193
+ let rv = unsafe {
194
+ ll_bindings:: tsk_population_table_add_row (
195
+ & mut ( * self . table ) ,
196
+ md. as_ptr ( ) ,
197
+ md. len ( ) . into ( ) ,
198
+ )
199
+ } ;
200
+
201
+ handle_tsk_return_value ! ( rv, PopulationId :: from( rv) )
202
+ }
203
+ }
204
+
205
+ impl std:: ops:: Deref for OwnedPopulationTable {
206
+ type Target = PopulationTable < ' static > ;
207
+
208
+ fn deref ( & self ) -> & Self :: Target {
209
+ // SAFETY: that T* and &T have same layout,
210
+ // and Target is repr(transparent).
211
+ unsafe { std:: mem:: transmute ( & self . table ) }
212
+ }
213
+ }
214
+
215
+ impl Default for OwnedPopulationTable {
216
+ fn default ( ) -> Self {
217
+ Self :: new ( )
218
+ }
219
+ }
0 commit comments