rill_protocol/
range.rs

1use ordered_float::OrderedFloat;
2use serde::{Deserialize, Serialize};
3use std::ops::Deref;
4
5// TODO: Consider removing (use `rillrate-protocol::Range` instead)
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
7pub struct Range {
8    min: OrderedFloat<f64>,
9    max: OrderedFloat<f64>,
10}
11
12impl Range {
13    pub fn new(mut min: f64, mut max: f64) -> Self {
14        if min > max {
15            std::mem::swap(&mut min, &mut max);
16        }
17        Self {
18            min: OrderedFloat::from(min),
19            max: OrderedFloat::from(max),
20        }
21    }
22
23    pub fn min(&self) -> f64 {
24        *self.min
25    }
26
27    pub fn max(&self) -> f64 {
28        *self.max
29    }
30
31    pub fn diff(&self) -> f64 {
32        *(self.max - self.min)
33    }
34
35    pub fn clamp(&self, value: &mut f64) {
36        if *value < *self.min {
37            *value = *self.min
38        } else if *value > *self.max {
39            *value = *self.max
40        }
41    }
42
43    pub fn pct(&self, value: f64) -> Pct {
44        Pct::from_range(value, self)
45    }
46}
47
48impl From<(f64, f64)> for Range {
49    fn from((min, max): (f64, f64)) -> Self {
50        Range::new(min, max)
51    }
52}
53
54#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
55pub struct Pct(f64);
56
57impl Default for Pct {
58    fn default() -> Self {
59        Self(0.0)
60    }
61}
62
63impl Pct {
64    pub fn from_value(mut value: f64) -> Self {
65        // TODO: Use `clamp` here.
66        if value < 0.0 {
67            value = 0.0;
68        } else if value > 1.0 {
69            value = 1.0;
70        }
71        Self(value)
72    }
73
74    pub fn from_div(value: f64, total: f64) -> Self {
75        let pct = {
76            if total == 0.0 {
77                0.0
78            } else {
79                value / total
80            }
81        };
82        Pct::from_value(pct)
83    }
84
85    pub fn from_range(value: f64, range: &Range) -> Self {
86        let value = value - range.min();
87        let diff = range.diff();
88        Pct::from_div(value, diff)
89    }
90
91    pub fn to_cent(self) -> f64 {
92        (self.0 * 100.0).round()
93    }
94}
95
96impl Deref for Pct {
97    type Target = f64;
98
99    fn deref(&self) -> &Self::Target {
100        &self.0
101    }
102}