Skip to main content

wowlab_engine_domain/rotation/lower/
eval_kind.rs

1#[cfg(feature = "rotation-optimizations")]
2use super::ops::spell::spell_enabled;
3use super::{
4    super::{
5        backend::RotationBackend, buffer::EvalKind, context::SpellUsableOffsets, expr::FieldType,
6    },
7    EvalValueAbstract,
8    ops::{
9        aura::aura_refreshable,
10        cooldown::{cooldown_full_recharge, cooldown_ready},
11        direct::positive_float,
12        resource::{resource_deficit, resource_deficit_pct, resource_pct, resource_time_to_max},
13        spell::{SpellUsableArgs, spell_usable},
14        timestamp,
15        unit::{unit_health_deficit, unit_health_pct},
16    },
17    typed_load,
18};
19
20#[derive(Clone, Copy)]
21pub(super) struct EvalInputs<'a> {
22    pub(super) spell_usable: Option<&'a SpellUsableOffsets>,
23    pub(super) cooldown_bypass_aura_offset: Option<usize>,
24    pub(super) spell_usability_prevalidated: bool,
25}
26
27// #t(fn: rust_cyclomatic_complexity) flat exhaustive match over the 16 EvalKind variants.
28pub(super) fn lower_eval_kind<B>(
29    b: &mut B,
30    kind: EvalKind,
31    offset: usize,
32    field_type: FieldType,
33    inputs: EvalInputs<'_>,
34) -> EvalValueAbstract<B>
35where
36    B: RotationBackend,
37{
38    match kind {
39        EvalKind::Direct => typed_load(b, offset, field_type),
40        EvalKind::TimestampReady => EvalValueAbstract::Bool(timestamp::ready(b, offset)),
41        EvalKind::TimestampRemaining => EvalValueAbstract::Float(timestamp::remaining(b, offset)),
42        EvalKind::TimestampActive => EvalValueAbstract::Bool(timestamp::active(b, offset)),
43        EvalKind::TimestampElapsed => EvalValueAbstract::Float(timestamp::elapsed(b, offset)),
44        EvalKind::TimestampInactive => EvalValueAbstract::Bool(timestamp::inactive(b, offset)),
45        EvalKind::CooldownReady => EvalValueAbstract::Bool(cooldown_ready(
46            b,
47            offset,
48            inputs.cooldown_bypass_aura_offset,
49        )),
50        EvalKind::CooldownFullRecharge => {
51            EvalValueAbstract::Float(cooldown_full_recharge(b, offset))
52        }
53        EvalKind::AuraRefreshable => EvalValueAbstract::Bool(aura_refreshable(b, offset)),
54        EvalKind::PositiveFloat => EvalValueAbstract::Bool(positive_float(b, offset)),
55        EvalKind::ResourceDeficit => EvalValueAbstract::Float(resource_deficit(b, offset)),
56        EvalKind::ResourcePct => EvalValueAbstract::Float(resource_pct(b, offset)),
57        EvalKind::ResourceDeficitPct => EvalValueAbstract::Float(resource_deficit_pct(b, offset)),
58        EvalKind::ResourceTimeToMax => EvalValueAbstract::Float(resource_time_to_max(b, offset)),
59        EvalKind::UnitHealthPct => EvalValueAbstract::Float(unit_health_pct(b, offset)),
60        EvalKind::UnitHealthDeficit => EvalValueAbstract::Float(unit_health_deficit(b, offset)),
61        EvalKind::SpellUsable => {
62            #[cfg(feature = "rotation-optimizations")]
63            if inputs.spell_usability_prevalidated {
64                return EvalValueAbstract::Bool(spell_enabled(b, offset));
65            }
66
67            #[cfg(not(feature = "rotation-optimizations"))]
68            let _ = inputs.spell_usability_prevalidated;
69
70            // Missing extras (impossible for valid rotations) degrades to the bare is_enabled check.
71            let args = match inputs.spell_usable {
72                Some(e) => SpellUsableArgs::from_offsets(offset, e),
73                None => SpellUsableArgs::bare(offset),
74            };
75
76            EvalValueAbstract::Bool(spell_usable(b, &args))
77        }
78        // `EvalKind` is `#[non_exhaustive]`, so this mandatory wildcard arm catches unhandled variants.
79        _ => {
80            debug_assert!(
81                false,
82                "lower_eval_kind: unhandled EvalKind variant {kind:?} (offset {offset}, {field_type:?})"
83            );
84            tracing::warn!(
85                ?kind,
86                offset,
87                ?field_type,
88                "lower_eval_kind: unhandled EvalKind variant, falling back to direct load"
89            );
90
91            typed_load(b, offset, field_type)
92        }
93    }
94}