use crate::abi::RateId;
#[cfg(feature = "unstable")]
use crate::rates::Rate;
use crate::rates::combine;
use super::{FakeHost, Installed, table};
impl FakeHost {
#[must_use]
#[cfg(feature = "unstable")]
pub fn without_rate(mut self, rate: Rate) -> Self {
self.missing_rates.insert(rate.id());
self
}
}
#[expect(
clippy::unused_self,
reason = "the fake's state is process-wide; `self` proves it is installed"
)]
impl Installed {
#[must_use]
#[cfg(feature = "unstable")]
pub fn rate(&self, rate: Rate) -> Option<f32> {
self.rate_of(rate.id())
}
pub(crate) fn rate_of(&self, id: RateId) -> Option<f32> {
table::with(None, |s| {
s.rates
.iter()
.find(|&&(declared, _)| declared == id)
.map(|&(_, factor)| combine([factor]))
})
}
}
#[cfg(test)]
#[cfg(feature = "unstable")]
mod tests {
use crate::abi::{HostApi, ModHandle, Status};
use crate::rates::{ExperienceGroup, Rate};
use crate::test::FakeHost;
use crate::test::table::TABLE;
fn api(_loader: &crate::test::Installed) -> &'static HostApi {
&TABLE
}
#[test]
fn a_declared_rate_starts_vanilla_and_takes_the_factor_set() {
let loader = FakeHost::new().install();
let api = api(&loader);
let rate = Rate::Experience(ExperienceGroup::Mining);
assert_eq!((api.rate)(ModHandle(1), rate.id()), Status::OK);
assert_eq!(loader.rate(rate), Some(1.0));
assert_eq!((api.set_rate)(ModHandle(1), rate.id(), 2.5), Status::OK);
assert_eq!(loader.rate(rate), Some(2.5));
}
#[test]
fn the_fake_refuses_what_the_loader_refuses() {
let loader = FakeHost::new()
.without_rate(Rate::FactoryProductionSpeed)
.install();
let api = api(&loader);
let speed = Rate::FactoryProductionSpeed.id();
let drops = Rate::ResourceDropStackAmount.id();
assert_eq!((api.rate)(ModHandle(1), speed), Status::MISSING);
assert_eq!(
(api.rate)(ModHandle(1), crate::abi::RateId(0)),
Status::BAD_ARGS
);
assert_eq!((api.set_rate)(ModHandle(1), drops, 2.0), Status::BAD_ARGS);
assert_eq!((api.rate)(ModHandle(1), drops), Status::OK);
for factor in [-0.5, 100.5, f32::NAN, f32::INFINITY] {
assert_eq!(
(api.set_rate)(ModHandle(1), drops, factor),
Status::BAD_ARGS
);
}
assert_eq!(loader.rate(Rate::ResourceDropStackAmount), Some(1.0));
}
}