use crate::metadata;
use crate::metadata::EdgeMetadata;
use crate::sys;
use crate::Position;
use crate::TskitError;
use crate::{EdgeId, NodeId};
use ll_bindings::tsk_id_t;
use sys::bindings as ll_bindings;
#[derive(Debug)]
pub struct EdgeTableRow {
pub id: EdgeId,
pub left: Position,
pub right: Position,
pub parent: NodeId,
pub child: NodeId,
pub metadata: Option<Vec<u8>>,
}
impl PartialEq for EdgeTableRow {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& self.parent == other.parent
&& self.child == other.child
&& crate::util::partial_cmp_equal(&self.left, &other.left)
&& crate::util::partial_cmp_equal(&self.right, &other.right)
&& self.metadata == other.metadata
}
}
fn make_edge_table_row(table: &EdgeTable, pos: tsk_id_t) -> Option<EdgeTableRow> {
Some(EdgeTableRow {
id: pos.into(),
left: table.left(pos)?,
right: table.right(pos)?,
parent: table.parent(pos)?,
child: table.child(pos)?,
metadata: table.table_.raw_metadata(pos).map(|m| m.to_vec()),
})
}
pub(crate) type EdgeTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a EdgeTable>;
pub(crate) type EdgeTableIterator = crate::table_iterator::TableIterator<EdgeTable>;
impl Iterator for EdgeTableRefIterator<'_> {
type Item = EdgeTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_edge_table_row(self.table, self.pos);
self.pos += 1;
rv
}
}
impl Iterator for EdgeTableIterator {
type Item = EdgeTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_edge_table_row(&self.table, self.pos);
self.pos += 1;
rv
}
}
#[derive(Debug)]
pub struct EdgeTableRowView<'a> {
table: &'a EdgeTable,
pub id: EdgeId,
pub left: Position,
pub right: Position,
pub parent: NodeId,
pub child: NodeId,
pub metadata: Option<&'a [u8]>,
}
impl<'a> EdgeTableRowView<'a> {
fn new(table: &'a EdgeTable) -> Self {
Self {
table,
id: (-1).into(),
left: f64::NAN.into(),
right: f64::NAN.into(),
parent: NodeId::NULL,
child: NodeId::NULL,
metadata: None,
}
}
}
impl PartialEq for EdgeTableRowView<'_> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& self.parent == other.parent
&& self.child == other.child
&& crate::util::partial_cmp_equal(&self.left, &other.left)
&& crate::util::partial_cmp_equal(&self.right, &other.right)
&& self.metadata == other.metadata
}
}
impl Eq for EdgeTableRowView<'_> {}
impl PartialEq<EdgeTableRow> for EdgeTableRowView<'_> {
fn eq(&self, other: &EdgeTableRow) -> bool {
self.id == other.id
&& self.parent == other.parent
&& self.child == other.child
&& crate::util::partial_cmp_equal(&self.left, &other.left)
&& crate::util::partial_cmp_equal(&self.right, &other.right)
&& optional_container_comparison!(self.metadata, other.metadata)
}
}
impl PartialEq<EdgeTableRowView<'_>> for EdgeTableRow {
fn eq(&self, other: &EdgeTableRowView) -> bool {
self.id == other.id
&& self.parent == other.parent
&& self.child == other.child
&& crate::util::partial_cmp_equal(&self.left, &other.left)
&& crate::util::partial_cmp_equal(&self.right, &other.right)
&& optional_container_comparison!(self.metadata, other.metadata)
}
}
impl crate::StreamingIterator for EdgeTableRowView<'_> {
type Item = Self;
row_lending_iterator_get!();
fn advance(&mut self) {
self.id = (i32::from(self.id) + 1).into();
self.left = self.table.left(self.id).unwrap_or_else(|| f64::NAN.into());
self.right = self.table.right(self.id).unwrap_or_else(|| f64::NAN.into());
self.parent = self.table.parent(self.id).unwrap_or(NodeId::NULL);
self.child = self.table.child(self.id).unwrap_or(NodeId::NULL);
self.metadata = self.table.table_.raw_metadata(self.id);
}
}
#[repr(transparent)]
#[derive(Debug, Default)]
pub struct EdgeTable {
table_: sys::EdgeTable,
}
impl EdgeTable {
pub fn new() -> Result<Self, TskitError> {
let table_ = sys::EdgeTable::new(0)?;
Ok(Self { table_ })
}
pub(crate) unsafe fn new_from_table(
edges: *mut ll_bindings::tsk_edge_table_t,
) -> Result<Self, TskitError> {
let ptr = std::ptr::NonNull::new(edges).unwrap();
let table_ = unsafe { sys::EdgeTable::new_borrowed(ptr) };
Ok(EdgeTable { table_ })
}
pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_edge_table_t {
self.table_.as_ref()
}
pub fn num_rows(&self) -> crate::SizeType {
self.as_ref().num_rows.into()
}
pub fn parent<E: Into<EdgeId> + Copy>(&self, row: E) -> Option<NodeId> {
self.table_.parent(row.into())
}
pub fn child<E: Into<EdgeId> + Copy>(&self, row: E) -> Option<NodeId> {
self.table_.child(row.into())
}
pub fn left<E: Into<EdgeId> + Copy>(&self, row: E) -> Option<Position> {
self.table_.left(row.into())
}
pub fn right<E: Into<EdgeId> + Copy>(&self, row: E) -> Option<Position> {
self.table_.right(row.into())
}
pub fn metadata<T: metadata::EdgeMetadata>(
&self,
row: impl Into<EdgeId>,
) -> Option<Result<T, TskitError>> {
let buffer = self.table_.raw_metadata(row)?;
Some(decode_metadata_row!(T, buffer).map_err(|e| e.into()))
}
pub fn iter(&self) -> impl Iterator<Item = EdgeTableRow> + '_ {
crate::table_iterator::make_table_iterator::<&EdgeTable>(self)
}
pub fn lending_iter<'table>(&'table self) -> EdgeTableRowView<'table> {
EdgeTableRowView::new(self)
}
pub fn row<E: Into<EdgeId> + Copy>(&self, r: E) -> Option<EdgeTableRow> {
table_row_access!(r.into().into(), self, make_edge_table_row)
}
pub fn row_view<'table, E: Into<EdgeId> + Copy>(
&'table self,
r: E,
) -> Option<EdgeTableRowView<'table>> {
let view = EdgeTableRowView {
table: self,
id: r.into(),
left: self.left(r)?,
right: self.right(r)?,
parent: self.parent(r)?,
child: self.child(r)?,
metadata: self.table_.raw_metadata(r.into()),
};
Some(view)
}
build_table_column_slice_getter!(
=> left, left_slice, Position);
build_table_column_slice_getter!(
=> left, left_slice_raw, f64);
build_table_column_slice_getter!(
=> right, right_slice, Position);
build_table_column_slice_getter!(
=> right, right_slice_raw, f64);
build_table_column_slice_getter!(
=> parent, parent_slice, NodeId);
build_table_column_slice_getter!(
=> parent, parent_slice_raw, ll_bindings::tsk_id_t);
build_table_column_slice_getter!(
=> child, child_slice, NodeId);
build_table_column_slice_getter!(
=> child, child_slice_raw, ll_bindings::tsk_id_t);
pub fn parent_column(&self) -> impl crate::TableColumn<EdgeId, NodeId> + '_ {
crate::table_column::OpaqueTableColumn(self.parent_slice())
}
pub fn child_column(&self) -> impl crate::TableColumn<EdgeId, NodeId> + '_ {
crate::table_column::OpaqueTableColumn(self.child_slice())
}
pub fn left_column(&self) -> impl crate::TableColumn<EdgeId, Position> + '_ {
crate::table_column::OpaqueTableColumn(self.left_slice())
}
pub fn right_column(&self) -> impl crate::TableColumn<EdgeId, Position> + '_ {
crate::table_column::OpaqueTableColumn(self.right_slice())
}
pub fn clear(&mut self) -> Result<i32, TskitError> {
handle_tsk_return_value!(self.table_.clear())
}
pub fn add_row<L: Into<Position>, R: Into<Position>, P: Into<NodeId>, C: Into<NodeId>>(
&mut self,
left: L,
right: R,
parent: P,
child: C,
) -> Result<EdgeId, TskitError> {
let rv = self.table_.add_row(
left.into().into(),
right.into().into(),
parent.into().into(),
child.into().into(),
)?;
handle_tsk_return_value!(rv, rv.into())
}
pub fn add_row_with_metadata<
L: Into<Position>,
R: Into<Position>,
P: Into<NodeId>,
C: Into<NodeId>,
M: EdgeMetadata,
>(
&mut self,
left: L,
right: R,
parent: P,
child: C,
metadata: &M,
) -> Result<EdgeId, TskitError> {
let md = crate::metadata::EncodedMetadata::new(metadata)?;
let rv = self.table_.add_row_with_metadata(
left.into().into(),
right.into().into(),
parent.into().into(),
child.into().into(),
md.as_slice(),
)?;
handle_tsk_return_value!(rv, rv.into())
}
}