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, Default, Clone, Copy, PartialEq, PartialOrd, AsRef, Deref, Display, Into)]
10pub struct Fraction(f32);
11
12/// Error that occurs when calling [`Fraction::new`].
13#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Error)]
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}
22
23impl Fraction {
24    /// Create a [`Fraction`].
25    pub fn new(value: f32) -> Result<Self, ConversionError> {
26        use ConversionError::*;
27        if value >= 1.0 {
28            return Err(UpperBound);
29        }
30        if value < 0.0 {
31            return Err(LowerBound);
32        }
33        Ok(Fraction(value))
34    }
35}
36
37impl TryFrom<f32> for Fraction {
38    type Error = ConversionError;
39    fn try_from(value: f32) -> Result<Self, Self::Error> {
40        Fraction::new(value)
41    }
42}
43
44/// Error that occurs when converting a string into an instance of [`Fraction`].
45#[derive(Debug, Display, Clone, PartialEq, Eq, Error)]
46pub enum FromStrError {
47    ParseFloatError(ParseFloatError),
48    Conversion(ConversionError),
49}
50
51impl FromStr for Fraction {
52    type Err = FromStrError;
53    fn from_str(text: &str) -> Result<Self, Self::Err> {
54        text.parse::<f32>()
55            .map_err(FromStrError::ParseFloatError)?
56            .try_into()
57            .map_err(FromStrError::Conversion)
58    }
59}