use crate::metadata;
use crate::sys;
use crate::IndividualFlags;
use crate::IndividualId;
use crate::Location;
use crate::TskitError;
use ll_bindings::tsk_id_t;
use sys::bindings as ll_bindings;
#[derive(Debug)]
pub struct IndividualTableRow {
pub id: IndividualId,
pub flags: IndividualFlags,
pub location: Option<Vec<Location>>,
pub parents: Option<Vec<IndividualId>>,
pub metadata: Option<Vec<u8>>,
}
impl PartialEq for IndividualTableRow {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& self.flags == other.flags
&& self.parents == other.parents
&& self.metadata == other.metadata
&& self.location == other.location
}
}
#[derive(Debug)]
pub struct IndividualTableRowView<'a> {
table: &'a IndividualTable,
pub id: IndividualId,
pub flags: IndividualFlags,
pub location: Option<&'a [Location]>,
pub parents: Option<&'a [IndividualId]>,
pub metadata: Option<&'a [u8]>,
}
impl<'a> IndividualTableRowView<'a> {
fn new(table: &'a IndividualTable) -> Self {
Self {
table,
id: (-1_i32).into(),
flags: 0.into(),
location: None,
parents: None,
metadata: None,
}
}
}
impl PartialEq for IndividualTableRowView<'_> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& self.flags == other.flags
&& self.parents == other.parents
&& self.metadata == other.metadata
&& self.location == other.location
}
}
impl Eq for IndividualTableRowView<'_> {}
impl PartialEq<IndividualTableRow> for IndividualTableRowView<'_> {
fn eq(&self, other: &IndividualTableRow) -> bool {
self.id == other.id
&& self.flags == other.flags
&& optional_container_comparison!(self.parents, other.parents)
&& optional_container_comparison!(self.metadata, other.metadata)
&& optional_container_comparison!(self.location, other.location)
}
}
impl PartialEq<IndividualTableRowView<'_>> for IndividualTableRow {
fn eq(&self, other: &IndividualTableRowView) -> bool {
self.id == other.id
&& self.flags == other.flags
&& optional_container_comparison!(self.parents, other.parents)
&& optional_container_comparison!(self.metadata, other.metadata)
&& optional_container_comparison!(self.location, other.location)
}
}
impl crate::StreamingIterator for IndividualTableRowView<'_> {
type Item = Self;
row_lending_iterator_get!();
fn advance(&mut self) {
self.id = (i32::from(self.id) + 1).into();
self.flags = self.table.flags(self.id).unwrap_or_else(|| 0.into());
self.location = self.table.location(self.id);
self.parents = self.table.parents(self.id);
self.metadata = self.table.table_.raw_metadata(self.id);
}
}
#[derive(Debug, Default)]
#[repr(transparent)]
pub struct IndividualTable {
table_: sys::IndividualTable,
}
fn make_individual_table_row(table: &IndividualTable, pos: tsk_id_t) -> Option<IndividualTableRow> {
Some(IndividualTableRow {
id: pos.into(),
flags: table.flags(pos)?,
location: table.location(pos).map(|s| s.to_vec()),
parents: table.parents(pos).map(|s| s.to_vec()),
metadata: table.table_.raw_metadata(pos).map(|m| m.to_vec()),
})
}
pub(crate) type IndividualTableRefIterator<'a> =
crate::table_iterator::TableIterator<&'a IndividualTable>;
pub(crate) type IndividualTableIterator = crate::table_iterator::TableIterator<IndividualTable>;
impl Iterator for IndividualTableRefIterator<'_> {
type Item = IndividualTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_individual_table_row(self.table, self.pos);
self.pos += 1;
rv
}
}
impl Iterator for IndividualTableIterator {
type Item = IndividualTableRow;
fn next(&mut self) -> Option<Self::Item> {
let rv = make_individual_table_row(&self.table, self.pos);
self.pos += 1;
rv
}
}
impl IndividualTable {
pub(crate) unsafe fn new_from_table(
individuals: *mut ll_bindings::tsk_individual_table_t,
) -> Result<Self, TskitError> {
let ptr = std::ptr::NonNull::new(individuals).unwrap();
let table_ = unsafe { sys::IndividualTable::new_borrowed(ptr) };
Ok(IndividualTable { table_ })
}
pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_individual_table_t {
self.table_.as_ref()
}
pub fn num_rows(&self) -> crate::SizeType {
self.as_ref().num_rows.into()
}
pub fn flags<I: Into<IndividualId> + Copy>(&self, row: I) -> Option<IndividualFlags> {
self.table_.flags(row.into())
}
pub fn location<I: Into<IndividualId> + Copy>(&self, row: I) -> Option<&[Location]> {
self.table_.location(row.into())
}
pub fn parents<I: Into<IndividualId> + Copy>(&self, row: I) -> Option<&[IndividualId]> {
self.table_.parents(row.into())
}
#[cfg_attr(
feature = "derive",
doc = r##"
```compile_fail
# #[derive(serde::Serialize, serde::Deserialize, tskit::metadata::MutationMetadata)]
# #[serializer("serde_json")]
# struct MutationMetadata {
# x: i32,
# }
#
# let mut tables = tskit::TableCollection::new(10.).unwrap();
match tables.individuals().metadata::<MutationMetadata>(0)
{
Some(Ok(metadata)) => assert_eq!(metadata.x, 1),
Some(Err(_)) => panic!("got an error??"),
None => panic!("Got None??"),
};
```
"##
)]
pub fn metadata<T: metadata::IndividualMetadata>(
&self,
row: impl Into<IndividualId>,
) -> 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 = IndividualTableRow> + '_ {
crate::table_iterator::make_table_iterator::<&IndividualTable>(self)
}
pub fn lending_iter(&'_ self) -> IndividualTableRowView<'_> {
IndividualTableRowView::new(self)
}
pub fn row<I: Into<IndividualId> + Copy>(&self, r: I) -> Option<IndividualTableRow> {
let ri = r.into().into();
table_row_access!(ri, self, make_individual_table_row)
}
pub fn row_view<I: Into<IndividualId> + Copy>(
&'_ self,
r: I,
) -> Option<IndividualTableRowView<'_>> {
let view = IndividualTableRowView {
table: self,
id: r.into(),
flags: self.flags(r)?,
location: self.location(r),
parents: self.parents(r),
metadata: self.table_.raw_metadata(r.into()),
};
Some(view)
}
build_table_column_slice_getter!(
=> flags, flags_slice, IndividualFlags);
build_table_column_slice_getter!(
=> flags, flags_slice_raw, ll_bindings::tsk_flags_t);
pub fn clear(&mut self) -> Result<i32, TskitError> {
handle_tsk_return_value!(self.table_.clear())
}
pub fn add_row<F, L, P>(
&mut self,
flags: F,
location: L,
parents: P,
) -> Result<IndividualId, TskitError>
where
F: Into<IndividualFlags>,
L: crate::IndividualLocation,
P: crate::IndividualParents,
{
let location = unsafe {
std::slice::from_raw_parts(
location.get_slice().as_ptr().cast::<f64>(),
location.get_slice().len(),
)
};
let parents = unsafe {
std::slice::from_raw_parts(
parents.get_slice().as_ptr().cast::<tsk_id_t>(),
parents.get_slice().len(),
)
};
let rv = self
.table_
.add_row(flags.into().bits(), location, parents)?;
handle_tsk_return_value!(rv, rv.into())
}
pub fn add_row_with_metadata<F, L, P, M>(
&mut self,
flags: F,
location: L,
parents: P,
metadata: &M,
) -> Result<IndividualId, TskitError>
where
F: Into<IndividualFlags>,
L: crate::IndividualLocation,
P: crate::IndividualParents,
M: crate::metadata::IndividualMetadata,
{
let md = crate::metadata::EncodedMetadata::new(metadata)?;
let location = unsafe {
std::slice::from_raw_parts(
location.get_slice().as_ptr().cast::<f64>(),
location.get_slice().len(),
)
};
let parents = unsafe {
std::slice::from_raw_parts(
parents.get_slice().as_ptr().cast::<tsk_id_t>(),
parents.get_slice().len(),
)
};
let rv = self.table_.add_row_with_metadata(
flags.into().bits(),
location,
parents,
md.as_slice(),
)?;
handle_tsk_return_value!(rv, rv.into())
}
}