use super::error::{GrammarError, GrammarResult};
pub trait ResourceScale<D, R> {
fn scale(&self, request: D) -> R;
fn domain(&self) -> (D, D);
fn range(&self) -> (R, R);
}
#[derive(Debug, Clone)]
pub struct LinearResourceScale {
domain: (f64, f64),
range: (f64, f64),
}
impl LinearResourceScale {
pub fn new(domain: (f64, f64), range: (f64, f64)) -> GrammarResult<Self> {
if domain.0 >= domain.1 {
return Err(GrammarError::InvalidScaleDomain {
min: domain.0,
max: domain.1,
});
}
Ok(Self { domain, range })
}
}
impl ResourceScale<f64, f64> for LinearResourceScale {
fn scale(&self, request: f64) -> f64 {
let t = (request - self.domain.0) / (self.domain.1 - self.domain.0);
self.range.0 + t * (self.range.1 - self.range.0)
}
fn domain(&self) -> (f64, f64) {
self.domain
}
fn range(&self) -> (f64, f64) {
self.range
}
}
#[derive(Debug, Clone)]
pub struct LogResourceScale {
base: f64,
domain: (f64, f64),
range: (f64, f64),
}
impl LogResourceScale {
pub fn new(base: f64, domain: (f64, f64), range: (f64, f64)) -> GrammarResult<Self> {
if domain.0 >= domain.1 {
return Err(GrammarError::InvalidScaleDomain {
min: domain.0,
max: domain.1,
});
}
Ok(Self {
base,
domain,
range,
})
}
}
impl ResourceScale<f64, f64> for LogResourceScale {
fn scale(&self, request: f64) -> f64 {
let log_request = request.log(self.base);
let log_min = self.domain.0.log(self.base);
let log_max = self.domain.1.log(self.base);
let t = (log_request - log_min) / (log_max - log_min);
self.range.0 + t * (self.range.1 - self.range.0)
}
fn domain(&self) -> (f64, f64) {
self.domain
}
fn range(&self) -> (f64, f64) {
self.range
}
}