siglus_scene_vm/runtime/
unknown.rs1use super::opcode::OpCode;
8use std::collections::BTreeMap;
9
10#[derive(Debug, Default)]
11pub struct UnknownOpRecorder {
12 pub codes: BTreeMap<OpCode, u64>,
14 pub names: BTreeMap<String, u64>,
16 pub notes: BTreeMap<String, u64>,
18
19 pub element_chains: BTreeMap<String, u64>,
24}
25
26impl UnknownOpRecorder {
27 pub fn record_code(&mut self, code: OpCode) {
28 *self.codes.entry(code).or_insert(0) += 1;
29 }
30
31 pub fn record_name(&mut self, name: &str) {
32 *self.names.entry(name.to_string()).or_insert(0) += 1;
33 }
34
35 pub fn record_note(&mut self, tag: &str) {
36 *self.notes.entry(tag.to_string()).or_insert(0) += 1;
37 }
38
39 pub fn record_element_chain(&mut self, form_id: u32, chain: &[i32], note: &str) {
40 let mut s = String::new();
41 s.push_str(&form_id.to_string());
42 for c in chain {
43 s.push(':');
44 s.push_str(&c.to_string());
45 }
46 if !note.is_empty() {
47 s.push_str(" @");
48 s.push_str(note);
49 }
50 *self.element_chains.entry(s).or_insert(0) += 1;
51 }
52
53 pub fn summary_string(&self, max_items: usize) -> String {
55 let mut out = String::new();
56
57 if !self.codes.is_empty() {
58 out.push_str("unknown numeric codes:\n");
59 for (i, (k, v)) in self.codes.iter().enumerate() {
60 if i >= max_items {
61 out.push_str(" ...\n");
62 break;
63 }
64 out.push_str(&format!(" form {} x{}\n", k.id, v));
65 }
66 }
67
68 if !self.notes.is_empty() {
69 out.push_str("runtime notes:\n");
70 for (i, (k, v)) in self.notes.iter().enumerate() {
71 if i >= max_items {
72 out.push_str(" ...\n");
73 break;
74 }
75 out.push_str(&format!(" {k} x{v}\n"));
76 }
77 }
78
79 if !self.names.is_empty() {
80 out.push_str("unknown named commands:\n");
81 for (i, (k, v)) in self.names.iter().enumerate() {
82 if i >= max_items {
83 out.push_str(" ...\n");
84 break;
85 }
86 out.push_str(&format!(" {k} x{v}\n"));
87 }
88 }
89
90 if !self.element_chains.is_empty() {
91 out.push_str("unknown element chains:\n");
92 for (i, (k, v)) in self.element_chains.iter().enumerate() {
93 if i >= max_items {
94 out.push_str(" ...\n");
95 break;
96 }
97 out.push_str(&format!(" {k} x{v}\n"));
98 }
99 }
100
101 if out.is_empty() {
102 out.push_str("(no unknown ops recorded)\n");
103 }
104
105 out
106 }
107}