use serde::{Deserialize, Serialize};
use crate::error::{MyIdError, MyIdResult};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(try_from = "f64", into = "f64")]
pub struct Threshold(f64);
impl Threshold {
pub const MIN: f64 = 0.5;
pub const MAX: f64 = 0.99;
pub const DEFAULT: Self = Self(0.75);
pub fn parse(value: f64) -> MyIdResult<Self> {
if !value.is_finite() {
return Err(MyIdError::validation(format!(
"threshold must be a finite number, got: {value}"
)));
}
if !(Self::MIN..=Self::MAX).contains(&value) {
return Err(MyIdError::validation(format!(
"threshold must be between {} and {}, got: {value}",
Self::MIN,
Self::MAX,
)));
}
Ok(Self(value))
}
#[inline]
pub fn as_f64(self) -> f64 {
self.0
}
}
impl std::fmt::Display for Threshold {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl TryFrom<f64> for Threshold {
type Error = MyIdError;
fn try_from(value: f64) -> MyIdResult<Self> {
Self::parse(value)
}
}
impl From<Threshold> for f64 {
fn from(value: Threshold) -> Self {
value.0
}
}
impl Eq for Threshold {}
impl std::hash::Hash for Threshold {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.to_bits().hash(state);
}
}