Skip to main content

parallel_disk_usage/args/
fraction.rs

1use derive_more::{AsRef, Deref, Display, Error, Into};
2use std::{
3    convert::{TryFrom, TryInto},
4    num::ParseFloatError,
5    str::FromStr,
6};
7
8/// Floating-point value that is greater than or equal to 0 and less than 1.
9#[derive(Debug, Display, Default, Clone, Copy, PartialEq, PartialOrd, AsRef, Deref, Into)]
10pub struct Fraction(f32);
11
12/// Error that occurs when calling [`Fraction::new`].
13#[derive(Debug, Display, Error, Clone, Copy, PartialEq, Eq)]
14pub enum ConversionError {
15    /// Provided value is greater than or equal to 1.
16    #[display("greater than or equal to 1")]
17    UpperBound,
18    /// Provided value is less than 0.
19    #[display("less than 0")]
20    LowerBound,
21    /// Provided value is `NaN`.
22    #[display("not a number")]
23    NotANumber,
24}
25
26impl Fraction {
27    /// Create a [`Fraction`].
28    pub fn new(value: f32) -> Result<Self, ConversionError> {
29        use ConversionError::*;
30        if value.is_nan() {
31            return Err(NotANumber);
32        }
33        if value >= 1.0 {
34            return Err(UpperBound);
35        }
36        if value < 0.0 {
37            return Err(LowerBound);
38        }
39        Ok(Fraction(value))
40    }
41}
42
43impl TryFrom<f32> for Fraction {
44    type Error = ConversionError;
45    fn try_from(value: f32) -> Result<Self, Self::Error> {
46        Fraction::new(value)
47    }
48}
49
50/// Error that occurs when parsing a string as [`Fraction`].
51#[derive(Debug, Display, Error, Clone, PartialEq, Eq)]
52pub enum FromStrError {
53    ParseFloatError(ParseFloatError),
54    Conversion(ConversionError),
55}
56
57impl FromStr for Fraction {
58    type Err = FromStrError;
59    fn from_str(text: &str) -> Result<Self, Self::Err> {
60        text.parse::<f32>()
61            .map_err(FromStrError::ParseFloatError)?
62            .try_into()
63            .map_err(FromStrError::Conversion)
64    }
65}