Skip to content

Commit

Permalink
Replace WrappedTskArray with idiomatic slices. Closes #99 (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
molpopgen authored Apr 27, 2021
1 parent ed8329b commit 89d234f
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 158 deletions.
30 changes: 8 additions & 22 deletions src/_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,28 +168,6 @@ macro_rules! process_state_input {
};
}

macro_rules! index_for_wrapped_tsk_array_type {
($name: ty, $index:ty, $output: ty) => {
impl std::ops::Index<$index> for $name {
type Output = $output;

fn index(&self, index: $index) -> &Self::Output {
if index >= self.len() as $index {
panic!("fatal: index out of range");
}
let rv = unsafe { self.array.offset(index as isize) };
unsafe { &*rv }
}
}
};
}

macro_rules! wrapped_tsk_array_traits {
($name: ty, $index:ty, $output: ty) => {
index_for_wrapped_tsk_array_type!($name, $index, $output);
};
}

macro_rules! err_if_not_tracking_samples {
($flags: expr, $rv: expr) => {
match $flags.contains(crate::TreeFlags::SAMPLE_LISTS) {
Expand Down Expand Up @@ -228,6 +206,14 @@ macro_rules! iterator_for_nodeiterator {
};
}

macro_rules! tree_array_slice {
($self: ident, $array: ident, $len: expr) => {
unsafe {
std::slice::from_raw_parts((*$self.as_ptr()).$array as *const tsk_id_t, $len as usize)
}
};
}

#[cfg(test)]
mod test {
use crate::error::TskitError;
Expand Down
115 changes: 0 additions & 115 deletions src/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,5 @@
//! Define traits related to wrapping tskit stuff
/// Indexable, iterable wrapper around C
/// arrays.
#[derive(Copy, Clone)]
pub struct WrappedTskArray<T> {
array: *const T,
len_: crate::tsk_size_t,
}

pub struct WrappedTskArrayIter<'a, T: Copy + 'a> {
inner: &'a WrappedTskArray<T>,
pos: crate::tsk_size_t,
}

impl<'a, T: Copy> Iterator for WrappedTskArrayIter<'a, T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.inner.len_ {
None
} else {
let rv = Some(unsafe { *self.inner.array.offset(self.pos as isize) as T });
self.pos += 1;
rv
}
}
}

impl<T: Copy> WrappedTskArray<T> {
pub(crate) fn new(array: *const T, len: crate::tsk_size_t) -> Self {
Self { array, len_: len }
}

pub fn len(&self) -> crate::tsk_size_t {
self.len_
}

pub fn is_empty(&self) -> bool {
self.len_ == 0
}

/// # Safety
///
/// This function returns the raw C pointer,
/// and is thus unsafe.
pub fn as_ptr(&self) -> *const T {
self.array
}

pub fn iter(&self) -> WrappedTskArrayIter<T> {
WrappedTskArrayIter {
inner: self,
pos: 0,
}
}
}

pub(crate) type TskIdArray = WrappedTskArray<crate::tsk_id_t>;
pub(crate) type Tskf64Array = WrappedTskArray<f64>;

wrapped_tsk_array_traits!(TskIdArray, crate::tsk_id_t, crate::tsk_id_t);
wrapped_tsk_array_traits!(Tskf64Array, crate::tsk_id_t, f64);

/// Wrap a tskit type
pub(crate) trait WrapTskitType<T> {
/// Encapsulate tsk_foo_t and return rust
Expand All @@ -83,7 +21,6 @@ pub(crate) trait WrapTskitConsumingType<T, C> {
mod tests {
use super::*;
use crate::bindings as ll_bindings;
use crate::tsk_size_t;
use crate::TskitTypeAccess;
use ll_bindings::tsk_table_collection_free;

Expand Down Expand Up @@ -119,56 +56,4 @@ mod tests {
let t = TableCollectionMock::new(10.);
assert_eq!(t.sequence_length() as i64, 10);
}

#[test]
fn test_u32_array_wrapper() {
let mut t = TableCollectionMock::new(10.);

let rv = unsafe {
ll_bindings::tsk_edge_table_add_row(
&mut (*t.as_mut_ptr()).edges,
0.,
10.,
0,
17,
std::ptr::null(),
0,
)
};
panic_on_tskit_error!(rv);

let a = TskIdArray::new(unsafe { (*t.as_ptr()).edges.child }, 1);
assert_eq!(a.len(), 1);
assert_eq!(a[0], 17);

let mut v = vec![];
for i in a.iter() {
v.push(i);
}
assert_eq!(v.len() as tsk_size_t, a.len());
assert_eq!(v[0], 17);
}

#[should_panic]
#[test]
fn test_u32_array_wrapper_panic() {
let mut t = TableCollectionMock::new(10.);

let rv = unsafe {
ll_bindings::tsk_edge_table_add_row(
&mut (*t.as_mut_ptr()).edges,
0.,
10.,
0,
17,
std::ptr::null(),
0,
)
};
panic_on_tskit_error!(rv);

let a = TskIdArray::new(unsafe { (*t.as_ptr()).edges.child }, 1);
assert_eq!(a.len(), 1);
assert_eq!(a[1], 17);
}
}
Loading

0 comments on commit 89d234f

Please sign in to comment.