1use super::error::{GrammarError, GrammarResult};
4
5pub trait ResourceScale<D, R> {
7 fn scale(&self, request: D) -> R;
9 fn domain(&self) -> (D, D);
11 fn range(&self) -> (R, R);
13}
14
15#[derive(Debug, Clone)]
17pub struct LinearResourceScale {
18 domain: (f64, f64),
19 range: (f64, f64),
20}
21
22impl LinearResourceScale {
23 pub fn new(domain: (f64, f64), range: (f64, f64)) -> GrammarResult<Self> {
25 if domain.0 >= domain.1 {
26 return Err(GrammarError::InvalidScaleDomain {
27 min: domain.0,
28 max: domain.1,
29 });
30 }
31 Ok(Self { domain, range })
32 }
33}
34
35impl ResourceScale<f64, f64> for LinearResourceScale {
36 fn scale(&self, request: f64) -> f64 {
37 let t = (request - self.domain.0) / (self.domain.1 - self.domain.0);
38 self.range.0 + t * (self.range.1 - self.range.0)
39 }
40
41 fn domain(&self) -> (f64, f64) {
42 self.domain
43 }
44
45 fn range(&self) -> (f64, f64) {
46 self.range
47 }
48}
49
50#[derive(Debug, Clone)]
52pub struct LogResourceScale {
53 base: f64,
54 domain: (f64, f64),
55 range: (f64, f64),
56}
57
58impl LogResourceScale {
59 pub fn new(base: f64, domain: (f64, f64), range: (f64, f64)) -> GrammarResult<Self> {
61 if domain.0 >= domain.1 {
62 return Err(GrammarError::InvalidScaleDomain {
63 min: domain.0,
64 max: domain.1,
65 });
66 }
67 Ok(Self {
68 base,
69 domain,
70 range,
71 })
72 }
73}
74
75impl ResourceScale<f64, f64> for LogResourceScale {
76 fn scale(&self, request: f64) -> f64 {
77 let log_request = request.log(self.base);
78 let log_min = self.domain.0.log(self.base);
79 let log_max = self.domain.1.log(self.base);
80 let t = (log_request - log_min) / (log_max - log_min);
81 self.range.0 + t * (self.range.1 - self.range.0)
82 }
83
84 fn domain(&self) -> (f64, f64) {
85 self.domain
86 }
87
88 fn range(&self) -> (f64, f64) {
89 self.range
90 }
91}