use crate::sys::bindings;
use crate::TskitError;
use bindings::tsk_id_t;
use bindings::tsk_size_t;
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct NodeId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct IndividualId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct PopulationId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct SiteId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct MutationId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct MigrationId(tsk_id_t);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct EdgeId(tsk_id_t);
impl_id_traits!(NodeId);
impl_id_traits!(IndividualId);
impl_id_traits!(PopulationId);
impl_id_traits!(SiteId);
impl_id_traits!(MutationId);
impl_id_traits!(MigrationId);
impl_id_traits!(EdgeId);
impl_size_type_comparisons_for_row_ids!(NodeId);
impl_size_type_comparisons_for_row_ids!(EdgeId);
impl_size_type_comparisons_for_row_ids!(SiteId);
impl_size_type_comparisons_for_row_ids!(MutationId);
impl_size_type_comparisons_for_row_ids!(PopulationId);
impl_size_type_comparisons_for_row_ids!(MigrationId);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct SizeType(tsk_size_t);
impl SizeType {
pub fn to_usize(&self) -> Option<usize> {
(*self).try_into().ok()
}
pub fn as_usize(&self) -> usize {
self.0 as usize
}
}
impl std::fmt::Display for SizeType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<tsk_size_t> for SizeType {
fn from(value: tsk_size_t) -> Self {
Self(value)
}
}
impl From<SizeType> for tsk_size_t {
fn from(value: SizeType) -> Self {
value.0
}
}
impl TryFrom<SizeType> for usize {
type Error = TskitError;
fn try_from(value: SizeType) -> Result<Self, Self::Error> {
match usize::try_from(value.0) {
Ok(x) => Ok(x),
Err(_) => Err(TskitError::RangeError(format!(
"could not convert {} to usize",
value
))),
}
}
}
impl TryFrom<usize> for SizeType {
type Error = TskitError;
fn try_from(value: usize) -> Result<Self, Self::Error> {
match tsk_size_t::try_from(value) {
Ok(x) => Ok(Self(x)),
Err(_) => Err(TskitError::RangeError(format!(
"could not convert usize {} to SizeType",
value
))),
}
}
}
impl TryFrom<tsk_id_t> for SizeType {
type Error = crate::TskitError;
fn try_from(value: tsk_id_t) -> Result<Self, Self::Error> {
match tsk_size_t::try_from(value) {
Ok(v) => Ok(Self(v)),
Err(_) => Err(crate::TskitError::RangeError(
stringify!(value.0).to_string(),
)),
}
}
}
impl TryFrom<SizeType> for tsk_id_t {
type Error = crate::TskitError;
fn try_from(value: SizeType) -> Result<Self, Self::Error> {
match tsk_id_t::try_from(value.0) {
Ok(v) => Ok(v),
Err(_) => Err(TskitError::RangeError(stringify!(value.0).to_string())),
}
}
}
impl PartialEq<SizeType> for tsk_size_t {
fn eq(&self, other: &SizeType) -> bool {
*self == other.0
}
}
impl PartialEq<tsk_size_t> for SizeType {
fn eq(&self, other: &tsk_size_t) -> bool {
self.0 == *other
}
}
impl PartialOrd<tsk_size_t> for SizeType {
fn partial_cmp(&self, other: &tsk_size_t) -> Option<std::cmp::Ordering> {
self.0.partial_cmp(other)
}
}
impl PartialOrd<SizeType> for tsk_size_t {
fn partial_cmp(&self, other: &SizeType) -> Option<std::cmp::Ordering> {
self.partial_cmp(&other.0)
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Time(f64);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Position(f64);
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Location(f64);
impl_f64_newtypes!(Time);
impl_f64_newtypes!(Position);
impl_f64_newtypes!(Location);
impl_time_position_arithmetic!(Time, Position);
impl_time_position_arithmetic!(Position, Time);
#[cfg(feature = "provenance")]
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
pub struct ProvenanceId(tsk_id_t);
#[cfg(feature = "provenance")]
impl_id_traits!(ProvenanceId);
#[test]
fn test_f64_newtype_Display() {
let x = Position::from(1.0);
let mut output = String::new();
std::fmt::write(&mut output, format_args!("{}", x))
.expect("Error occurred while trying to write in String");
assert_eq!(output, "1".to_string());
let x = Time::from(1.0);
let mut output = String::new();
std::fmt::write(&mut output, format_args!("{}", x))
.expect("Error occurred while trying to write in String");
assert_eq!(output, "1".to_string());
let x = Location::from(1.0);
let mut output = String::new();
std::fmt::write(&mut output, format_args!("{}", x))
.expect("Error occurred while trying to write in String");
assert_eq!(output, "1".to_string());
}
#[test]
fn test_usize_to_size_type() {
let x = usize::MAX;
let s = SizeType::try_from(x).ok();
#[cfg(target_pointer_width = "64")]
assert_eq!(s, Some(bindings::tsk_size_t::MAX.into()));
#[cfg(target_pointer_width = "32")]
assert_eq!(s, Some((usize::MAX as bindings::tsk_size_t).into()));
let x = usize::MIN;
let s = SizeType::try_from(x).ok();
assert_eq!(s, Some(0.into()));
}
#[test]
fn test_from_reference() {
let x = 2;
let y = NodeId::from(&x);
assert_eq!(y, 2);
assert_eq!(2, tsk_id_t::from(&y));
}
#[test]
fn test_try_from_reference() {
let y = NodeId::from(2);
assert_eq!(2, usize::try_from(&y).unwrap());
}
#[test]
fn test_eq_to_self_ref() {
let x = NodeId::from(1);
let rx = &x;
assert_eq!(x, rx);
assert_eq!(rx, x);
}
#[test]
fn test_ord_to_self_ref() {
let x = NodeId::from(1);
let y = NodeId::from(2);
let ry = &y;
assert!(x < ry);
assert!(ry > x);
}