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.offsets.slots.cooldowns.keys().copied().collect(),
25                |key| key.0,
26            ),
27            |out, &key| {
28                if let Some(value) = self.cooldown(key) {
29                    let _ = writeln!(out, "  spell={}", key.0);
30
31                    value.dump_fields(out);
32                }
33            },
34        );
35        dump_keyed(
36            &mut out,
37            "[auras]\n",
38            sorted_by_key(self.offsets.slots.auras.keys().copied().collect(), |key| {
39                let on = match key.on() {
40                    AuraOn::Player => 0,
41                    AuraOn::Target => 1,
42                    AuraOn::Pet => PET_AURA_SORT_RANK,
43                };
44
45                (key.aura(), key.source(), key.affected(), on)
46            }),
47            |out, &key| {
48                if let Some(value) = self.aura(key) {
49                    let _ = writeln!(
50                        out,
51                        "  aura={} source={:?} affected={:?} on={:?}",
52                        key.aura().0,
53                        key.source(),
54                        key.affected(),
55                        key.on()
56                    );
57
58                    value.dump_fields(out);
59                }
60            },
61        );
62        dump_keyed(
63            &mut out,
64            "[spells]\n",
65            sorted_by_key(self.offsets.slots.spells.keys().copied().collect(), |key| {
66                key.0
67            }),
68            |out, &key| {
69                if let Some(value) = self.spell(key) {
70                    let _ = writeln!(out, "  spell={}", key.0);
71
72                    value.dump_fields(out);
73                }
74            },
75        );
76        dump_keyed(
77            &mut out,
78            "[talents]\n",
79            sorted_by_key(
80                self.offsets.slots.talents.keys().cloned().collect(),
81                Clone::clone,
82            ),
83            |out, key| {
84                if let Some(value) = self.talent(key) {
85                    let _ = writeln!(out, "  talent={key}");
86
87                    value.dump_fields(out);
88                }
89            },
90        );
91        dump_keyed(
92            &mut out,
93            "[resources]\n",
94            sorted_by_key(
95                self.offsets.slots.resources.keys().copied().collect(),
96                |key| u8::from(*key),
97            ),
98            |out, &key| {
99                if let Some(value) = self.resource(key) {
100                    let _ = writeln!(out, "  {key}");
101
102                    value.dump_fields(out);
103                }
104            },
105        );
106        dump_keyed(
107            &mut out,
108            "[units]\n",
109            sorted_by_key(
110                self.offsets.slots.units.keys().cloned().collect(),
111                Clone::clone,
112            ),
113            |out, key| {
114                if let Some(value) = self.unit(key) {
115                    let _ = writeln!(out, "  role={key}");
116
117                    value.dump_fields(out);
118                }
119            },
120        );
121        dump_keyed(
122            &mut out,
123            "[standalone]\n",
124            sorted_by_key(
125                self.offsets
126                    .standalone
127                    .iter()
128                    .map(|(&id, &offset)| (id.get(), offset.as_usize()))
129                    .collect(),
130                |&(descriptor_id, _)| descriptor_id,
131            ),
132            |out, &(descriptor_id, offset)| {
133                let _ = writeln!(out, "  descriptor_id={descriptor_id:<6} offset={offset}");
134            },
135        );
136
137        out
138    }
139}
140
141fn dump_keyed<K>(out: &mut String, section: &str, keys: Vec<K>, emit: impl Fn(&mut String, &K)) {
142    if keys.is_empty() {
143        return;
144    }
145
146    out.push_str(section);
147
148    for key in keys {
149        emit(out, &key);
150    }
151}
152
153fn sorted_by_key<K, S>(mut values: Vec<K>, key: impl Fn(&K) -> S) -> Vec<K>
154where
155    S: Ord,
156{
157    values.sort_by_key(key);
158
159    values
160}