use crate::metadata;
use crate::metadata::SiteMetadata;
use crate::sys;
use crate::sys::bindings as ll_bindings;
use crate::Position;
use crate::SiteId;
use crate::SizeType;
use crate::TskitError;
use ll_bindings::tsk_id_t;
#[derive(Debug)]
pub struct SiteTableRow {
pub id: SiteId,
pub position: Position,
pub ancestral_state: Option<Vec<u8>>,
pub metadata: Option<Vec<u8>>,
}
impl PartialEq for SiteTableRow {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& crate::util::partial_cmp_equal(&self.position, &other.position)
&& self.ancestral_state == other.ancestral_state
&& self.metadata == other.metadata
}
}
fn make_site_table_row(table: &SiteTable, pos: tsk_id_t) -> Option<SiteTableRow> {
let ancestral_state = table.ancestral_state(pos).map(|s| s.to_vec());
Some(SiteTableRow {
id: pos.into(),
position: table.position(pos)?,
ancestral_state,
metadata: table.table_.raw_metadata(pos).map(|m| m.to_vec()),
})
}
pub(crate) type SiteTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a SiteTable>;
pub(crate) type SiteTableIterator = crate::table_iterator::TableIterator<SiteTable>;
impl Iterator for SiteTableRefIterator<'_> {
type Item = SiteTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_site_table_row(self.table, self.pos);
self.pos += 1;
rv
}
}
impl Iterator for SiteTableIterator {
type Item = SiteTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_site_table_row(&self.table, self.pos);
self.pos += 1;
rv
}
}
#[derive(Debug)]
pub struct SiteTableRowView<'a> {
table: &'a SiteTable,
pub id: SiteId,
pub position: Position,
pub ancestral_state: Option<&'a [u8]>,
pub metadata: Option<&'a [u8]>,
}
impl<'a> SiteTableRowView<'a> {
fn new(table: &'a SiteTable) -> Self {
Self {
table,
id: SiteId::NULL,
position: f64::NAN.into(),
ancestral_state: None,
metadata: None,
}
}
}
impl PartialEq for SiteTableRowView<'_> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& crate::util::partial_cmp_equal(&self.position, &other.position)
&& self.ancestral_state == other.ancestral_state
&& self.metadata == other.metadata
}
}
impl Eq for SiteTableRowView<'_> {}
impl PartialEq<SiteTableRow> for SiteTableRowView<'_> {
fn eq(&self, other: &SiteTableRow) -> bool {
self.id == other.id
&& crate::util::partial_cmp_equal(&self.position, &other.position)
&& optional_container_comparison!(self.ancestral_state, other.ancestral_state)
&& optional_container_comparison!(self.metadata, other.metadata)
}
}
impl PartialEq<SiteTableRowView<'_>> for SiteTableRow {
fn eq(&self, other: &SiteTableRowView) -> bool {
self.id == other.id
&& crate::util::partial_cmp_equal(&self.position, &other.position)
&& optional_container_comparison!(self.ancestral_state, other.ancestral_state)
&& optional_container_comparison!(self.metadata, other.metadata)
}
}
impl crate::StreamingIterator for SiteTableRowView<'_> {
type Item = Self;
row_lending_iterator_get!();
fn advance(&mut self) {
self.id = (i32::from(self.id) + 1).into();
self.position = self
.table
.position(self.id)
.unwrap_or_else(|| f64::NAN.into());
self.ancestral_state = self.table.ancestral_state(self.id);
self.metadata = self.table.table_.raw_metadata(self.id);
}
}
#[derive(Debug, Default)]
#[repr(transparent)]
pub struct SiteTable {
table_: sys::SiteTable,
}
impl SiteTable {
pub(crate) unsafe fn new_from_table(
sites: *mut ll_bindings::tsk_site_table_t,
) -> Result<Self, TskitError> {
let ptr = std::ptr::NonNull::new(sites).unwrap();
let table_ = unsafe { sys::SiteTable::new_borrowed(ptr) };
Ok(SiteTable { table_ })
}
pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_site_table_t {
self.table_.as_ref()
}
pub fn num_rows(&self) -> SizeType {
self.as_ref().num_rows.into()
}
pub fn position<S: Into<SiteId> + Copy>(&self, row: S) -> Option<Position> {
self.table_.position(row.into())
}
pub fn ancestral_state<S: Into<SiteId>>(&self, row: S) -> Option<&[u8]> {
self.table_.ancestral_state(row.into())
}
pub fn metadata<T: metadata::SiteMetadata>(
&self,
row: impl Into<SiteId>,
) -> Option<Result<T, TskitError>> {
let buffer = self.table_.raw_metadata(row)?;
Some(decode_metadata_row!(T, buffer).map_err(TskitError::from))
}
pub fn iter(&self) -> impl Iterator<Item = SiteTableRow> + '_ {
crate::table_iterator::make_table_iterator::<&SiteTable>(self)
}
pub fn lending_iter(&'_ self) -> SiteTableRowView<'_> {
SiteTableRowView::new(self)
}
pub fn row<S: Into<SiteId> + Copy>(&self, r: S) -> Option<SiteTableRow> {
let ri = r.into().into();
table_row_access!(ri, self, make_site_table_row)
}
pub fn row_view<S: Into<SiteId> + Copy>(&'_ self, r: S) -> Option<SiteTableRowView<'_>> {
let view = SiteTableRowView {
table: self,
id: r.into(),
position: self.position(r)?,
ancestral_state: self.ancestral_state(r),
metadata: self.table_.raw_metadata(r.into()),
};
Some(view)
}
build_table_column_slice_getter!(
=> position, position_slice, Position);
build_table_column_slice_getter!(
=> position, position_slice_raw, f64);
pub fn position_column(&self) -> impl crate::TableColumn<SiteId, Position> + '_ {
crate::table_column::OpaqueTableColumn(self.position_slice())
}
pub fn clear(&mut self) -> Result<i32, TskitError> {
handle_tsk_return_value!(self.table_.clear())
}
pub fn add_row<P: Into<Position>>(
&mut self,
position: P,
ancestral_state: Option<&[u8]>,
) -> Result<SiteId, TskitError> {
let rv = self
.table_
.add_row(position.into().into(), ancestral_state)?;
handle_tsk_return_value!(rv, rv.into())
}
pub fn add_row_with_metadata<P: Into<Position>, M: SiteMetadata>(
&mut self,
position: P,
ancestral_state: Option<&[u8]>,
metadata: &M,
) -> Result<SiteId, TskitError> {
let md = crate::metadata::EncodedMetadata::new(metadata)?;
let rv = self.table_.add_row_with_metadata(
position.into().into(),
ancestral_state,
md.as_slice(),
)?;
handle_tsk_return_value!(rv, rv.into())
}
}