wowlab_parsers/parsers/transform/
spec.rs1use wowlab_types::data::SpecDataFlat;
2
3#[cfg(feature = "dbc")]
4use super::{super::dbc::DbcData, super::errors::TransformError, resolve_icon_file_name};
5
6pub fn transform_spec(dbc: &DbcData, spec_id: i32) -> Result<SpecDataFlat, TransformError> {
12 let spec = dbc
13 .chr_specialization
14 .get(&spec_id)
15 .ok_or_else(|| TransformError::spec_not_found(spec_id))?;
16
17 let class_name = spec
18 .ClassID
19 .and_then(|class_id| dbc.chr_classes.get(&class_id))
20 .and_then(|c| c.Name_lang.clone())
21 .unwrap_or_default();
22
23 let file_name = resolve_icon_file_name(dbc, spec.SpellIconFileID);
24
25 Ok(SpecDataFlat {
26 id: spec.ID,
27 name: spec.Name_lang.clone().unwrap_or_default().into(),
28 description: spec.Description_lang.clone().unwrap_or_default(),
29 class_id: spec.ClassID.unwrap_or(0),
30 class_name: class_name.into(),
31 role: spec.Role,
32 order_index: spec.OrderIndex.unwrap_or(0),
33 icon_file_id: spec.SpellIconFileID,
34 file_name: file_name.into(),
35 primary_stat_priority: spec.PrimaryStatPriority,
36 mastery_spell_id_0: spec.MasterySpellID_0,
37 mastery_spell_id_1: spec.MasterySpellID_1,
38 })
39}
40
41#[must_use]
43pub fn transform_all_specs(dbc: &DbcData) -> Vec<SpecDataFlat> {
44 super::transform_all(dbc.chr_specialization.keys().copied(), "spec", |spec_id| {
45 transform_spec(dbc, spec_id)
46 })
47}
48
49#[cfg(test)]
50mod tests {
51 use googletest::prelude::*;
52
53 use super::*;
54 use crate::parsers::{
55 dbc::rows::{ChrClassesRow, ChrSpecializationRow},
56 transform::fixtures::{class_row, dbc, spec_row},
57 };
58
59 #[gtest]
60 fn transform_spec_missing_errors() -> Result<()> {
61 let dbc = dbc();
62
63 verify_that!(
64 transform_spec(&dbc, 260).unwrap_err().to_string(),
65 eq("Spec 260 not found in DBC cache")
66 )
67 }
68
69 #[gtest]
70 fn transform_spec_joins_class_name() -> Result<()> {
71 let mut dbc = dbc();
72
73 dbc.chr_classes.insert(
74 4,
75 ChrClassesRow {
76 Name_lang: Some("Rogue".to_string()),
77 ..class_row(4)
78 },
79 );
80 dbc.chr_specialization.insert(
81 260,
82 ChrSpecializationRow {
83 ClassID: Some(4),
84 OrderIndex: Some(2),
85 MasterySpellID_0: 76806,
86 MasterySpellID_1: 0,
87 ..spec_row(260)
88 },
89 );
90
91 let flat = transform_spec(&dbc, 260)?;
92
93 verify_that!(flat.class_id, eq(4))?;
94 verify_that!(flat.class_name.as_str(), eq("Rogue"))?;
95 verify_that!(flat.order_index, eq(2))?;
96
97 verify_that!(flat.mastery_spell_id_0, eq(76806))
98 }
99
100 #[gtest]
101 fn transform_spec_no_class_id_defaults() -> Result<()> {
102 let mut dbc = dbc();
103
104 dbc.chr_specialization.insert(
105 260,
106 ChrSpecializationRow {
107 ClassID: None,
108 ..spec_row(260)
109 },
110 );
111
112 let flat = transform_spec(&dbc, 260)?;
113
114 verify_that!(flat.class_id, eq(0))?;
115
116 verify_that!(flat.class_name.as_str(), eq(""))
117 }
118
119 #[gtest]
120 fn transform_spec_class_join_miss() -> Result<()> {
121 let mut dbc = dbc();
122
123 dbc.chr_specialization.insert(
124 260,
125 ChrSpecializationRow {
126 ClassID: Some(4),
127 OrderIndex: Some(1),
128 MasterySpellID_1: 999,
129 ..spec_row(260)
130 },
131 );
132
133 let flat = transform_spec(&dbc, 260)?;
134
135 verify_that!(flat.class_id, eq(4))?;
136 verify_that!(flat.class_name.as_str(), eq(""))?;
137 verify_that!(flat.order_index, eq(1))?;
138
139 verify_that!(flat.mastery_spell_id_1, eq(999))
140 }
141}