augurs_prophet/
positive_float.rs1#[repr(transparent)]
3#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
4#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
5#[cfg_attr(feature = "serde", derive(serde::Serialize))]
6pub struct PositiveFloat(f64);
7
8#[derive(Debug, thiserror::Error)]
10#[error("invalid float provided: {0}")]
11pub struct TryFromFloatError(f64);
12
13impl PositiveFloat {
14 pub fn try_new(f: f64) -> Result<Self, TryFromFloatError> {
20 if !f.is_finite() || f <= 0.0 {
21 return Err(TryFromFloatError(f));
22 }
23 Ok(Self(f))
24 }
25
26 pub const fn one() -> Self {
28 Self(1.0)
29 }
30}
31
32impl TryFrom<f64> for PositiveFloat {
33 type Error = TryFromFloatError;
34 fn try_from(value: f64) -> Result<Self, Self::Error> {
35 Self::try_new(value)
36 }
37}
38
39impl std::ops::Deref for PositiveFloat {
40 type Target = f64;
41 fn deref(&self) -> &Self::Target {
42 &self.0
43 }
44}
45
46impl From<PositiveFloat> for f64 {
47 fn from(value: PositiveFloat) -> Self {
48 value.0
49 }
50}
51
52#[cfg(feature = "serde")]
53impl<'de> serde::Deserialize<'de> for PositiveFloat {
54 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55 where
56 D: serde::Deserializer<'de>,
57 {
58 let f = f64::deserialize(deserializer)?;
59 Self::try_new(f).map_err(serde::de::Error::custom)
60 }
61}