Skip to main content

forge/profile/
categories.rs

1#[cfg(test)]
2use googletest::{Result as GtestResult, prelude::*};
3
4#[derive(Debug)]
5pub(super) struct Category {
6    pub name: &'static str,
7    pub patterns: &'static [&'static str],
8    pub description: &'static str,
9}
10
11#[rustfmt::skip]
12pub(super) static CATEGORIES: &[Category] = &[
13    Category {
14        name: "rotation",
15        patterns: &["wowlab_engine::rotation", "inkwell", "jit"],
16        description: "JIT-compiled rotation evaluation (Cranelift). Condition checks, expression trees, context population.",
17    },
18    Category {
19        name: "cast_pipeline",
20        patterns: &["wowlab_engine::cast"],
21        description: "CastEngine: unified cast pipeline. Costs, cooldowns, GCD, hooks (PreCast/PostCast/ModifyDamage).",
22    },
23    Category {
24        name: "damage",
25        patterns: &["wowlab_engine::combat::damage"],
26        description: "DamagePipeline: base + AP*coef + SP*coef, crit roll, multipliers, armor reduction.",
27    },
28    Category {
29        name: "auras",
30        patterns: &["wowlab_engine::combat::aura"],
31        description: "Buff/debuff tracking. AuraTracker manages active auras, stacking, duration, periodic ticks.",
32    },
33    Category {
34        name: "cooldowns",
35        patterns: &["wowlab_engine::combat::cooldown"],
36        description: "Cooldown and charge tracking per spell.",
37    },
38    Category {
39        name: "procs",
40        patterns: &["wowlab_engine::combat::proc"],
41        description: "Proc system: RPPM, proc flags, trigger dispatch via TriggerBus.",
42    },
43    Category {
44        name: "resources",
45        patterns: &["wowlab_engine::combat::resource"],
46        description: "Resource pools (Focus, Fury, etc.), regen, spending, waste tracking.",
47    },
48    Category {
49        name: "stats",
50        patterns: &["wowlab_engine::combat::stats", "wowlab_engine::combat::math"],
51        description: "Stat attributes, ratings, scaling coefficients, combat math.",
52    },
53    Category {
54        name: "actors",
55        patterns: &["wowlab_engine::combat::actor"],
56        description: "Player/enemy/pet actors. Initialization, stat setup, pet summoning.",
57    },
58    Category {
59        name: "sim_loop",
60        patterns: &["wowlab_engine::sim"],
61        description: "SimState, event queue, simulation executor, batch runner.",
62    },
63    Category {
64        name: "modules",
65        patterns: &["wowlab_engine::module", "wowlab_engine::specs"],
66        description: "Module composition (class + spec modules), ModuleHandler adapter, hook dispatch.",
67    },
68    Category {
69        name: "metrics",
70        patterns: &["wowlab_engine::metrics"],
71        description: "Metrics collection, descriptors, per-spell/aura tracking, exporters.",
72    },
73    Category {
74        name: "defs",
75        patterns: &["wowlab_engine::defs"],
76        description: "SpellDefinitionDraft, AuraDefinitionDraft, BuilderSpellDef, BuilderAuraDef, TalentDef. Spell/aura execution.",
77    },
78    Category {
79        name: "host",
80        patterns: &["wowlab_engine::host", "wowlab_engine::intent"],
81        description: "Host API, simulation request handling, intent schema.",
82    },
83    Category {
84        name: "data",
85        patterns: &[
86            "wowlab_engine::data",
87            "wowlab_engine::config",
88            "wowlab_parsers",
89            "wowlab_types::data",
90            "csv::",
91            "csv_core",
92            "serde",
93            "toml",
94        ],
95        description: "Data loading (DBC CSV parsing, resolver, item resolution).",
96    },
97    Category {
98        name: "collections",
99        patterns: &["hashbrown", "hash_map", "btree"],
100        description: "Hash maps, btrees, collection operations (not engine-specific).",
101    },
102    Category {
103        name: "memory",
104        patterns: &[
105            "alloc::",
106            "<alloc::",
107            "drop_in_place",
108            "dealloc",
109            "mi_",
110            "mmap",
111        ],
112        description: "Allocations, deallocations, Vec resizing, drop glue, mimalloc.",
113    },
114    Category {
115        name: "tracing",
116        patterns: &["tracing", "smallvec", "sharded_slab"],
117        description: "Tracing subscriber overhead (fmt layer, span storage, SmallVec alloc/drop).",
118    },
119];
120
121pub(super) fn classify(name: &str) -> &'static str {
122    let lower = name.to_lowercase();
123
124    for cat in CATEGORIES {
125        if cat
126            .patterns
127            .iter()
128            .any(|p| lower.contains(&p.to_lowercase()))
129        {
130            return cat.name;
131        }
132    }
133
134    if name.starts_with("std::") || name.starts_with("core::") || name.starts_with('_') {
135        return "stdlib";
136    }
137
138    "other"
139}
140
141pub(super) fn description(name: &str) -> &'static str {
142    for cat in CATEGORIES {
143        if cat.name == name {
144            return cat.description;
145        }
146    }
147
148    match name {
149        "stdlib" => "Rust stdlib/core (hashing, iterators, formatting, etc.).",
150        "other" => "Unclassified: anything not matching the above patterns.",
151        _ => "",
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158
159    #[gtest]
160    fn classify_routes_jit_symbols_to_rotation() -> GtestResult<()> {
161        verify_that!(classify("wowlab_engine::rotation::eval"), eq("rotation"))?;
162        verify_that!(classify("inkwell::execution_engine::run"), eq("rotation"))?;
163        verify_that!(classify("jit_compile"), eq("rotation"))?;
164
165        Ok(())
166    }
167
168    #[gtest]
169    fn classify_routes_cast_pipeline() -> GtestResult<()> {
170        verify_that!(
171            classify("wowlab_engine::cast::engine::run"),
172            eq("cast_pipeline")
173        )?;
174
175        Ok(())
176    }
177
178    #[gtest]
179    fn classify_routes_stdlib_prefixes_to_stdlib() -> GtestResult<()> {
180        verify_that!(classify("std::vec::Vec::push"), eq("stdlib"))?;
181        verify_that!(classify("core::option::Option::map"), eq("stdlib"))?;
182        verify_that!(classify("_ZN3std9panicking12default_hook"), eq("stdlib"))?;
183
184        Ok(())
185    }
186
187    #[gtest]
188    fn classify_unknown_falls_through_to_other() -> GtestResult<()> {
189        verify_that!(classify("totally_unrelated_function_name"), eq("other"))?;
190
191        Ok(())
192    }
193
194    #[gtest]
195    fn classify_is_case_insensitive() -> GtestResult<()> {
196        verify_that!(classify("WOWLAB_ENGINE::ROTATION::EVAL"), eq("rotation"))?;
197
198        Ok(())
199    }
200
201    #[gtest]
202    fn description_returns_table_entry_for_known_category() -> GtestResult<()> {
203        let desc = description("rotation");
204
205        verify_true!(desc.contains("JIT"))?;
206
207        Ok(())
208    }
209
210    #[gtest]
211    fn description_returns_synthetic_for_stdlib_and_other() -> GtestResult<()> {
212        verify_true!(description("stdlib").contains("stdlib"))?;
213        verify_true!(description("other").contains("Unclassified"))?;
214
215        Ok(())
216    }
217
218    #[gtest]
219    fn description_returns_empty_for_unknown_category() -> GtestResult<()> {
220        verify_that!(description("not_a_real_category"), eq(""))?;
221
222        Ok(())
223    }
224}