1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use crate::error::DemesError;
use serde::{Deserialize, Serialize};
/// The size of a [`Deme`](crate::Deme) at a given [`Time`](crate::Time).
///
/// This is a newtype wrapper for [`f64`](std::primitive::f64).
///
/// # Notes
///
/// * The size may take on non-integer values.
///
/// # Examples
///
/// ## In a `YAML` record
///
/// ```
/// let yaml = "
/// time_units: years
/// generation_time: 25
/// description:
/// A deme of 50 individuals that grew to 100 individuals
/// in the last 100 years.
/// demes:
/// - name: deme
/// epochs:
/// - start_size: 50
/// end_time: 100
/// - start_size: 50
/// end_size: 100
/// ";
/// demes::loads(yaml).unwrap();
/// ```
///
/// ## Using rust code
///
/// ```
/// let t = demes::DemeSize::try_from(50.0).unwrap();
/// assert_eq!(t, 50.0);
/// ```
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(try_from = "f64")]
#[repr(transparent)]
pub struct DemeSize(f64);
impl DemeSize {
fn validate<F>(&self, f: F) -> Result<(), DemesError>
where
F: std::ops::FnOnce(String) -> DemesError,
{
if self.0.is_nan() || self.0.is_infinite() || self.0 <= 0.0 {
let msg = format!("deme sizes must be 0 <= d < Infinity, got: {}", self.0);
Err(f(msg))
} else {
Ok(())
}
}
}
impl TryFrom<f64> for DemeSize {
type Error = DemesError;
fn try_from(value: f64) -> Result<Self, Self::Error> {
let rv = Self(value);
rv.validate(DemesError::ValueError)?;
Ok(rv)
}
}
impl_newtype_traits!(DemeSize);
/// Input value for [`DemeSize`], used when loading or building graphs.
///
/// # Examples
///
/// ```
/// let t = demes::InputDemeSize::from(1.0);
/// assert_eq!(t, 1.0);
/// let t = t - 1.0;
/// assert_eq!(t, 0.0);
/// let t = 1.0 + t;
/// assert_eq!(t, 1.0);
/// ```
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, PartialOrd)]
#[repr(transparent)]
#[serde(from = "f64")]
pub struct InputDemeSize(f64);
impl_input_newtype_traits!(InputDemeSize);
impl TryFrom<InputDemeSize> for DemeSize {
type Error = DemesError;
fn try_from(value: InputDemeSize) -> Result<Self, Self::Error> {
let rv = Self(value.0);
rv.validate(DemesError::ValueError)?;
Ok(rv)
}
}