@@ -5,64 +5,69 @@ use std::{
55
66use serde:: { Deserialize , Serialize } ;
77
8- #[ derive( PartialEq , PartialOrd , Clone , Copy , Serialize , Deserialize , sealedstruct:: Seal ) ]
9- pub struct PercentageRaw ( f64 ) ;
8+ #[ derive( PartialEq , PartialOrd , Clone , Copy , Serialize , Deserialize ) ]
9+ #[ serde( try_from = "f64" ) ]
10+ pub struct Percentage ( f64 ) ;
1011
1112#[ cfg( feature = "impex" ) ]
1213impl impex:: ImpexPrimitive for Percentage { }
1314
14- impl sealedstruct:: Validator for PercentageRaw {
15- fn check ( & self ) -> sealedstruct:: Result < ( ) > {
16- if * * self < 0. {
17- return sealedstruct:: ValidationError :: new ( format ! ( "{} is too small" , self . 0 ) ) . into ( ) ;
18- }
15+ #[ derive( Debug , thiserror:: Error ) ]
16+ #[ error( "Invalid percentage {0}" ) ]
17+ pub struct InvalidPercentage ( f64 ) ;
18+
19+ impl TryFrom < f64 > for Percentage {
20+ type Error = InvalidPercentage ;
1921
20- if * * self > 1. {
21- return sealedstruct:: ValidationError :: new ( format ! ( "{} is too big" , self . 0 ) ) . into ( ) ;
22+ fn try_from ( value : f64 ) -> Result < Self , Self :: Error > {
23+ if ( ( 0. ) ..=1. ) . contains ( & value) {
24+ Ok ( Percentage ( value) )
25+ } else {
26+ Err ( InvalidPercentage ( value) )
2227 }
23- Ok ( ( ) )
2428 }
2529}
2630
2731impl Percentage {
28- pub fn new ( i : f64 ) -> sealedstruct:: Result < Self > {
29- PercentageRaw ( i) . seal ( )
32+ pub const fn new ( value : f64 ) -> Option < Self > {
33+ if value >= 0. && value <= 1. {
34+ Some ( Percentage ( value) )
35+ } else {
36+ None
37+ }
3038 }
31- pub fn max ( ) -> Self {
32- Percentage :: new_unchecked ( PercentageRaw ( 1.0 ) )
39+
40+ pub const fn max ( ) -> Self {
41+ Percentage ( 1.0 )
3342 }
34- pub fn min ( ) -> Self {
35- Percentage :: new_unchecked ( PercentageRaw ( 0.0 ) )
43+ pub const fn min ( ) -> Self {
44+ Percentage ( 0.0 )
3645 }
3746
3847 pub fn fifty ( ) -> Self {
39- Percentage :: new_unchecked ( PercentageRaw ( 0.5 ) )
48+ Percentage ( 0.5 )
4049 }
4150}
4251
43- impl approx:: AbsDiffEq for PercentageRaw {
52+ impl approx:: AbsDiffEq for Percentage {
4453 type Epsilon = f64 ;
4554
4655 fn default_epsilon ( ) -> Self :: Epsilon {
4756 f64:: EPSILON
4857 }
4958
5059 fn abs_diff_eq ( & self , other : & Self , epsilon : Self :: Epsilon ) -> bool {
51- self . 0 . abs_diff_eq ( other, epsilon)
60+ self . 0 . abs_diff_eq ( & other. 0 , epsilon)
5261 }
5362}
5463
55- impl PercentageRaw {
56- pub fn new ( i : f64 ) -> Self {
57- Self ( i)
58- }
59-
64+ impl Percentage {
6065 pub fn value ( & self ) -> f64 {
6166 self . 0
6267 }
6368}
6469
65- impl Display for PercentageRaw {
70+ impl Display for Percentage {
6671 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
6772 f. write_fmt ( format_args ! ( "{}%" , self . 0 * 100. ) )
6873 }
@@ -74,42 +79,22 @@ impl Debug for Percentage {
7479 }
7580}
7681
77- impl std:: ops:: Sub for PercentageRaw {
78- type Output = PercentageRaw ;
82+ impl std:: ops:: Mul < f64 > for Percentage {
83+ type Output = f64 ;
7984
80- fn sub ( self , rhs : Self ) -> Self :: Output {
81- PercentageRaw ( self . 0 - rhs. 0 )
85+ fn mul ( self , rhs : f64 ) -> Self :: Output {
86+ self . 0 * rhs
8287 }
8388}
84-
85- impl std:: ops:: Add for PercentageRaw {
86- type Output = PercentageRaw ;
87-
88- fn add ( self , rhs : Self ) -> Self :: Output {
89- PercentageRaw ( self . 0 + rhs. 0 )
90- }
91- }
92-
93- impl std:: ops:: Mul for PercentageRaw {
94- type Output = PercentageRaw ;
89+ impl std:: ops:: Mul for Percentage {
90+ type Output = Percentage ;
9591
9692 fn mul ( self , rhs : Self ) -> Self :: Output {
97- PercentageRaw ( self . 0 * rhs. 0 )
98- }
99- }
100-
101- impl From < f64 > for Percentage {
102- fn from ( i : f64 ) -> Self {
103- Self ( i. into ( ) )
104- }
105- }
106- impl From < f64 > for PercentageRaw {
107- fn from ( i : f64 ) -> Self {
108- Self ( i)
93+ Percentage ( self . 0 * rhs. 0 )
10994 }
11095}
11196
112- impl Deref for PercentageRaw {
97+ impl Deref for Percentage {
11398 type Target = f64 ;
11499
115100 fn deref ( & self ) -> & Self :: Target {
@@ -123,7 +108,7 @@ mod tests {
123108
124109 #[ test]
125110 fn invalid_percentage ( ) {
126- assert ! ( PercentageRaw :: new( -1. ) . seal ( ) . is_err ( ) ) ;
127- assert ! ( PercentageRaw :: new( 1.1 ) . seal ( ) . is_err ( ) ) ;
111+ assert ! ( Percentage :: new( -1. ) . is_none ( ) ) ;
112+ assert ! ( Percentage :: new( 1.1 ) . is_none ( ) ) ;
128113 }
129114}
0 commit comments