1use serde::de::{self, Visitor};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt;
4pub use std::num::NonZeroUsize;
5
6#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
8pub struct UnitFraction(f64);
9
10impl UnitFraction {
11 pub fn new(v: f64) -> Result<Self, String> {
12 if (0.0..=1.0).contains(&v) {
13 Ok(Self(v))
14 } else {
15 Err(format!("{v} is outside [0.0, 1.0]"))
16 }
17 }
18 pub fn value(self) -> f64 {
19 self.0
20 }
21}
22
23impl Serialize for UnitFraction {
24 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
25 s.serialize_f64(self.0)
26 }
27}
28
29struct UnitFractionVisitor;
30
31impl Visitor<'_> for UnitFractionVisitor {
32 type Value = UnitFraction;
33
34 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 f.write_str("a float in [0.0, 1.0]")
36 }
37
38 fn visit_f64<E: de::Error>(self, v: f64) -> Result<UnitFraction, E> {
39 UnitFraction::new(v).map_err(de::Error::custom)
40 }
41
42 fn visit_i64<E: de::Error>(self, v: i64) -> Result<UnitFraction, E> {
43 self.visit_f64(v as f64)
44 }
45
46 fn visit_u64<E: de::Error>(self, v: u64) -> Result<UnitFraction, E> {
47 self.visit_f64(v as f64)
48 }
49}
50
51impl<'de> Deserialize<'de> for UnitFraction {
52 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
53 d.deserialize_f64(UnitFractionVisitor)
54 }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
59pub struct ZScoreThreshold(f64);
60
61impl ZScoreThreshold {
62 pub fn new(v: f64) -> Result<Self, String> {
63 if v > 0.0 {
64 Ok(Self(v))
65 } else {
66 Err(format!("{v} must be > 0.0"))
67 }
68 }
69 pub fn value(self) -> f64 {
70 self.0
71 }
72}
73
74impl Serialize for ZScoreThreshold {
75 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
76 s.serialize_f64(self.0)
77 }
78}
79
80struct ZScoreThresholdVisitor;
81
82impl Visitor<'_> for ZScoreThresholdVisitor {
83 type Value = ZScoreThreshold;
84
85 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 f.write_str("a float > 0.0")
87 }
88
89 fn visit_f64<E: de::Error>(self, v: f64) -> Result<ZScoreThreshold, E> {
90 ZScoreThreshold::new(v).map_err(de::Error::custom)
91 }
92
93 fn visit_i64<E: de::Error>(self, v: i64) -> Result<ZScoreThreshold, E> {
94 self.visit_f64(v as f64)
95 }
96
97 fn visit_u64<E: de::Error>(self, v: u64) -> Result<ZScoreThreshold, E> {
98 self.visit_f64(v as f64)
99 }
100}
101
102impl<'de> Deserialize<'de> for ZScoreThreshold {
103 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
104 d.deserialize_f64(ZScoreThresholdVisitor)
105 }
106}