Skip to main content

wowlab_engine_domain/rotation/buffer/dense/
dump.rs

1use std::fmt::Write as _;
2
3use wowlab_types::sim::AuraOn;
4
5use super::DenseBuffer;
6
7const PET_AURA_SORT_RANK: u8 = 2;
8
9impl DenseBuffer {
10    /// Produce a human-readable dump of the entire buffer state.
11    pub fn dump(&self) -> String {
12        // #t(rust_magic_numbers) estimated capacity for a typical buffer dump
13        let mut out = String::with_capacity(1024);
14
15        out.push_str("[player]\n");
16        self.player().dump_fields(&mut out);
17        out.push_str("[combat]\n");
18        self.combat().dump_fields(&mut out);
19
20        dump_keyed(
21            &mut out,
22            "[cooldowns]\n",
23            sorted_by_key(
24                self.layout
25                    .offsets
26                    .slots
27                    .cooldowns
28                    .keys()
29                    .copied()
30                    .collect(),
31                |key| key.0,
32            ),
33            |out, &key| {
34                if let Some(handle) = self.layout.cooldown_handle(key) {
35                    let value = self.cooldown_at(handle);
36                    let _ = writeln!(out, "  spell={}", key.0);
37
38                    value.dump_fields(out);
39                }
40            },
41        );
42        dump_keyed(
43            &mut out,
44            "[auras]\n",
45            sorted_by_key(
46                self.layout.offsets.slots.auras.keys().copied().collect(),
47                |key| {
48                    let on = match key.on() {
49                        AuraOn::Player => 0,
50                        AuraOn::Target => 1,
51                        AuraOn::Pet => PET_AURA_SORT_RANK,
52                    };
53
54                    (key.aura(), key.source(), key.affected(), on)
55                },
56            ),
57            |out, &key| {
58                if let Some(handle) = self.layout.aura_handle(key) {
59                    let value = self.aura_at(handle);
60                    let _ = writeln!(
61                        out,
62                        "  aura={} source={:?} affected={:?} on={:?}",
63                        key.aura().0,
64                        key.source(),
65                        key.affected(),
66                        key.on()
67                    );
68
69                    value.dump_fields(out);
70                }
71            },
72        );
73        dump_keyed(
74            &mut out,
75            "[spells]\n",
76            sorted_by_key(
77                self.layout.offsets.slots.spells.keys().copied().collect(),
78                |key| key.0,
79            ),
80            |out, &key| {
81                if let Some(handle) = self.layout.spell_handle(key) {
82                    let value = self.spell_at(handle);
83                    let _ = writeln!(out, "  spell={}", key.0);
84
85                    value.dump_fields(out);
86                }
87            },
88        );
89        dump_keyed(
90            &mut out,
91            "[talents]\n",
92            sorted_by_key(
93                self.layout.offsets.slots.talents.keys().cloned().collect(),
94                Clone::clone,
95            ),
96            |out, key| {
97                if let Some(handle) = self.layout.talent_handle(key) {
98                    let value = self.talent_at(handle);
99                    let _ = writeln!(out, "  talent={key}");
100
101                    value.dump_fields(out);
102                }
103            },
104        );
105        dump_keyed(
106            &mut out,
107            "[resources]\n",
108            sorted_by_key(
109                self.layout
110                    .offsets
111                    .slots
112                    .resources
113                    .keys()
114                    .copied()
115                    .collect(),
116                |key| u8::from(*key),
117            ),
118            |out, &key| {
119                if let Some(handle) = self.layout.resource_handle(key) {
120                    let value = self.resource_at(handle);
121                    let _ = writeln!(out, "  {key}");
122
123                    value.dump_fields(out);
124                }
125            },
126        );
127        dump_keyed(
128            &mut out,
129            "[units]\n",
130            sorted_by_key(
131                self.layout.offsets.slots.units.keys().cloned().collect(),
132                Clone::clone,
133            ),
134            |out, key| {
135                if let Some(handle) = self.layout.unit_handle(key) {
136                    let value = self.unit_at(handle);
137                    let _ = writeln!(out, "  role={key}");
138
139                    value.dump_fields(out);
140                }
141            },
142        );
143        dump_keyed(
144            &mut out,
145            "[standalone]\n",
146            sorted_by_key(
147                self.layout
148                    .offsets
149                    .standalone
150                    .iter()
151                    .map(|(&id, &offset)| (id.get(), offset.as_usize()))
152                    .collect(),
153                |&(descriptor_id, _)| descriptor_id,
154            ),
155            |out, &(descriptor_id, offset)| {
156                let _ = writeln!(out, "  descriptor_id={descriptor_id:<6} offset={offset}");
157            },
158        );
159
160        out
161    }
162}
163
164fn dump_keyed<K>(out: &mut String, section: &str, keys: Vec<K>, emit: impl Fn(&mut String, &K)) {
165    if keys.is_empty() {
166        return;
167    }
168
169    out.push_str(section);
170
171    for key in keys {
172        emit(out, &key);
173    }
174}
175
176fn sorted_by_key<K, S>(mut values: Vec<K>, key: impl Fn(&K) -> S) -> Vec<K>
177where
178    S: Ord,
179{
180    values.sort_by_key(key);
181
182    values
183}