Skip to content

Commit 0599db9

Browse files
committed
refactor: use sys::LowLevelPointerManager to manage ownership of C API types.
* All tables now have a single rust type behind them. * OwnedXTable is now a type alias for XTable. * remove several internal types and macros
1 parent 1818e11 commit 0599db9

11 files changed

+781
-663
lines changed

src/_macros.rs

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -380,56 +380,6 @@ macro_rules! handle_metadata_return {
380380
};
381381
}
382382

383-
macro_rules! build_owned_tables {
384-
($name: ty, $deref: ident, $lltype: ty, $tsktable: ty) => {
385-
impl $name {
386-
fn new() -> Self {
387-
let table = <$lltype>::new();
388-
Self { table }
389-
}
390-
391-
/// Clear the table.
392-
pub fn clear(&mut self) -> $crate::TskReturnValue {
393-
self.table.clear().map_err(|e| e.into())
394-
}
395-
}
396-
397-
impl Default for $name {
398-
fn default() -> Self {
399-
Self::new()
400-
}
401-
}
402-
403-
impl std::ops::Deref for $name {
404-
type Target = $deref;
405-
406-
fn deref(&self) -> &Self::Target {
407-
// SAFETY: that T* and &T have same layout,
408-
// and Target is repr(transparent).
409-
unsafe { std::mem::transmute(&self.table) }
410-
}
411-
}
412-
413-
impl std::ops::DerefMut for $name {
414-
fn deref_mut(&mut self) -> &mut Self::Target {
415-
// SAFETY: that T* and &T have same layout,
416-
// and Target is repr(transparent).
417-
unsafe { std::mem::transmute(&mut self.table) }
418-
}
419-
}
420-
421-
impl $name {
422-
pub fn as_ptr(&self) -> *const $tsktable {
423-
self.table.as_ptr()
424-
}
425-
426-
pub fn as_mut_ptr(&mut self) -> *mut $tsktable {
427-
self.table.as_mut_ptr()
428-
}
429-
}
430-
};
431-
}
432-
433383
macro_rules! node_table_add_row_details {
434384
($flags: ident,
435385
$time: ident,
@@ -929,25 +879,6 @@ macro_rules! provenance_table_add_row {
929879
};
930880
}
931881

932-
macro_rules! build_owned_table_type {
933-
($(#[$attr:meta])* => $name: ident,
934-
$deref_type: ident,
935-
$lltype: ty,
936-
$tsktable: ty) => {
937-
$(#[$attr])*
938-
pub struct $name {
939-
table: $lltype
940-
}
941-
942-
build_owned_tables!(
943-
$name,
944-
$deref_type,
945-
$lltype,
946-
$tsktable
947-
);
948-
};
949-
}
950-
951882
macro_rules! raw_metadata_getter_for_tables {
952883
($idtype: ty) => {
953884
fn raw_metadata<I: Into<$idtype>>(&self, row: I) -> Option<&[u8]> {

src/edge_table.rs

Lines changed: 76 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -137,29 +137,86 @@ impl<'a> streaming_iterator::StreamingIterator for EdgeTableRowView<'a> {
137137
}
138138
}
139139

140-
/// An immutable view of an edge table.
140+
/// An edge table.
141141
///
142-
/// These are not created directly but are accessed
143-
/// by types implementing [`std::ops::Deref`] to
144-
/// [`crate::table_views::TableViews`]
142+
/// # Examples
143+
///
144+
/// ## Standalone tables
145+
///
146+
/// ```
147+
/// use tskit::EdgeTable;
148+
///
149+
/// let mut edges = EdgeTable::default();
150+
/// let rowid = edges.add_row(1., 2., 0, 1).unwrap();
151+
/// assert_eq!(rowid, 0);
152+
/// assert_eq!(edges.num_rows(), 1);
153+
///
154+
/// edges.clear().unwrap();
155+
/// assert_eq!(edges.num_rows(), 0);
156+
/// ```
157+
///
158+
/// An example with metadata.
159+
/// This requires the cargo feature `"derive"` for `tskit`.
160+
///
161+
/// ```
162+
/// # #[cfg(any(feature="doc", feature="derive"))] {
163+
/// use tskit::EdgeTable;
164+
///
165+
/// #[derive(serde::Serialize,
166+
/// serde::Deserialize,
167+
/// tskit::metadata::EdgeMetadata)]
168+
/// #[serializer("serde_json")]
169+
/// struct EdgeMetadata {
170+
/// value: i32,
171+
/// }
172+
///
173+
/// let metadata = EdgeMetadata{value: 42};
174+
///
175+
/// let mut edges = EdgeTable::default();
176+
///
177+
/// let rowid = edges.add_row_with_metadata(0., 1., 5, 10, &metadata).unwrap();
178+
/// assert_eq!(rowid, 0);
179+
///
180+
/// match edges.metadata::<EdgeMetadata>(rowid) {
181+
/// // rowid is in range, decoding succeeded
182+
/// Some(Ok(decoded)) => assert_eq!(decoded.value, 42),
183+
/// // rowid is in range, decoding failed
184+
/// Some(Err(e)) => panic!("error decoding metadata: {:?}", e),
185+
/// None => panic!("row id out of range")
186+
/// }
187+
/// # }
188+
/// ```
145189
#[repr(transparent)]
146190
#[derive(Debug)]
147191
pub struct EdgeTable {
148-
table_: sys::LLEdgeTableRef,
192+
table_: sys::LLEdgeTable,
149193
}
150194

151195
impl EdgeTable {
196+
pub(crate) fn as_ptr(&self) -> *const ll_bindings::tsk_edge_table_t {
197+
self.table_.as_ptr()
198+
}
199+
200+
pub(crate) fn as_mut_ptr(&mut self) -> *mut ll_bindings::tsk_edge_table_t {
201+
self.table_.as_mut_ptr()
202+
}
203+
152204
pub(crate) fn new_from_table(
153205
edges: *mut ll_bindings::tsk_edge_table_t,
154206
) -> Result<Self, TskitError> {
155-
let table_ = sys::LLEdgeTableRef::new_from_table(edges)?;
207+
let table_ = sys::LLEdgeTable::new_non_owning(edges)?;
156208
Ok(EdgeTable { table_ })
157209
}
158210

159211
pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_edge_table_t {
160212
self.table_.as_ref()
161213
}
162214

215+
pub fn new() -> Result<Self, TskitError> {
216+
let table_ = sys::LLEdgeTable::new_owning(0)?;
217+
Ok(Self { table_ })
218+
}
219+
163220
/// Return the number of rows
164221
pub fn num_rows(&self) -> crate::SizeType {
165222
self.as_ref().num_rows.into()
@@ -283,6 +340,13 @@ impl EdgeTable {
283340
Some(view)
284341
}
285342

343+
pub fn clear(&mut self) -> Result<(), TskitError> {
344+
self.table_.clear().map_err(|e| e.into())
345+
}
346+
347+
edge_table_add_row!(=> add_row, self, self.as_mut_ptr());
348+
edge_table_add_row_with_metadata!(=> add_row_with_metadata, self, self.as_mut_ptr());
349+
286350
build_table_column_slice_getter!(
287351
/// Get the left column as a slice
288352
=> left, left_slice, Position);
@@ -309,61 +373,10 @@ impl EdgeTable {
309373
=> child, child_slice_raw, ll_bindings::tsk_id_t);
310374
}
311375

312-
build_owned_table_type!(
313-
/// A standalone edge table that owns its data.
314-
///
315-
/// # Examples
316-
///
317-
/// ```
318-
/// use tskit::OwningEdgeTable;
319-
///
320-
/// let mut edges = OwningEdgeTable::default();
321-
/// let rowid = edges.add_row(1., 2., 0, 1).unwrap();
322-
/// assert_eq!(rowid, 0);
323-
/// assert_eq!(edges.num_rows(), 1);
324-
///
325-
/// edges.clear().unwrap();
326-
/// assert_eq!(edges.num_rows(), 0);
327-
/// ```
328-
///
329-
/// An example with metadata.
330-
/// This requires the cargo feature `"derive"` for `tskit`.
331-
///
332-
/// ```
333-
/// # #[cfg(any(feature="doc", feature="derive"))] {
334-
/// use tskit::OwningEdgeTable;
335-
///
336-
/// #[derive(serde::Serialize,
337-
/// serde::Deserialize,
338-
/// tskit::metadata::EdgeMetadata)]
339-
/// #[serializer("serde_json")]
340-
/// struct EdgeMetadata {
341-
/// value: i32,
342-
/// }
343-
///
344-
/// let metadata = EdgeMetadata{value: 42};
345-
///
346-
/// let mut edges = OwningEdgeTable::default();
347-
///
348-
/// let rowid = edges.add_row_with_metadata(0., 1., 5, 10, &metadata).unwrap();
349-
/// assert_eq!(rowid, 0);
350-
///
351-
/// match edges.metadata::<EdgeMetadata>(rowid) {
352-
/// // rowid is in range, decoding succeeded
353-
/// Some(Ok(decoded)) => assert_eq!(decoded.value, 42),
354-
/// // rowid is in range, decoding failed
355-
/// Some(Err(e)) => panic!("error decoding metadata: {:?}", e),
356-
/// None => panic!("row id out of range")
357-
/// }
358-
/// # }
359-
/// ```
360-
=> OwningEdgeTable,
361-
EdgeTable,
362-
crate::sys::LLOwningEdgeTable,
363-
crate::bindings::tsk_edge_table_t
364-
);
365-
366-
impl OwningEdgeTable {
367-
edge_table_add_row!(=> add_row, self, self.as_mut_ptr());
368-
edge_table_add_row_with_metadata!(=> add_row_with_metadata, self, self.as_mut_ptr());
376+
impl Default for EdgeTable {
377+
fn default() -> Self {
378+
Self::new().unwrap()
379+
}
369380
}
381+
382+
pub type OwningEdgeTable = EdgeTable;

src/error.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ pub enum TskitError {
4040
impl From<crate::sys::Error> for TskitError {
4141
fn from(error: sys::Error) -> Self {
4242
match error {
43-
sys::Error::Message(msg) => TskitError::LibraryError(msg),
4443
sys::Error::Code(code) => TskitError::ErrorCode { code },
44+
sys::Error::Message(msg) => TskitError::LibraryError(msg),
45+
sys::Error::NullPointer => {
46+
TskitError::LibraryError("null pointer encountered".to_owned())
47+
}
4548
}
4649
}
4750
}

0 commit comments

Comments
 (0)