1use serde::{Deserialize, Serialize};
2#[cfg(feature = "wasm")]
3use tsify::Tsify;
4
5#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
7#[cfg_attr(feature = "wasm", derive(Tsify))]
8#[cfg_attr(feature = "wasm", tsify(into_wasm_abi))]
9#[serde(rename_all = "camelCase")]
10pub struct ParsedSpellDescription {
11 pub nodes: Vec<SpellDescriptionNode>,
12}
13
14#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
16#[cfg_attr(feature = "wasm", derive(Tsify))]
17#[serde(tag = "type", rename_all = "camelCase")]
18pub enum SpellDescriptionNode {
21 Text(TextNode),
22 Variable(VariableNode),
23 ExpressionBlock(ExpressionBlockNode),
24 Conditional(ConditionalNode),
25 Pluralization(PluralizationNode),
26 Gender(GenderNode),
27 ColorCode(ColorCodeNode),
28}
29#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
33#[cfg_attr(feature = "wasm", derive(Tsify))]
34#[serde(rename_all = "camelCase")]
35pub struct TextNode {
36 value: String,
37}
38
39impl TextNode {
40 pub(crate) fn new(value: String) -> Self {
41 Self { value }
42 }
43 pub fn value(&self) -> &str {
44 &self.value
45 }
46}
47
48#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
50#[cfg_attr(feature = "wasm", derive(Tsify))]
51#[serde(rename_all = "camelCase")]
52pub struct ColorCodeNode {
53 code: String,
54}
55
56impl ColorCodeNode {
57 pub(crate) fn new(code: String) -> Self {
58 Self { code }
59 }
60 pub fn code(&self) -> &str {
61 &self.code
62 }
63}
64
65#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
67#[cfg_attr(feature = "wasm", derive(Tsify))]
68#[serde(tag = "varKind", rename_all = "camelCase")]
69pub enum VariableNode {
71 Effect(EffectVariableNode),
72 SpellLevel(SpellLevelVariableNode),
73 Player(PlayerVariableNode),
74 CrossSpell(CrossSpellReferenceNode),
75 Custom(CustomVariableNode),
76 At(AtVariableNode),
77 Enchant(EnchantVariableNode),
78 Misc(MiscVariableNode),
79}
80
81#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
83#[cfg_attr(feature = "wasm", derive(Tsify))]
84#[serde(rename_all = "camelCase")]
85pub struct EffectVariableNode {
86 pub var_type: String,
87 pub effect_index: u8,
88}
89
90#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
92#[cfg_attr(feature = "wasm", derive(Tsify))]
93#[serde(rename_all = "camelCase")]
94pub struct SpellLevelVariableNode {
95 pub var_type: String,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub index: Option<u8>,
98}
99
100#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
102#[cfg_attr(feature = "wasm", derive(Tsify))]
103#[serde(rename_all = "camelCase")]
104pub struct PlayerVariableNode {
105 var_name: String,
106}
107
108impl PlayerVariableNode {
109 pub(crate) fn new(var_name: String) -> Self {
110 Self { var_name }
111 }
112 pub fn var_name(&self) -> &str {
113 &self.var_name
114 }
115}
116
117#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
119#[cfg_attr(feature = "wasm", derive(Tsify))]
120#[serde(rename_all = "camelCase")]
121pub struct CrossSpellReferenceNode {
122 pub spell_id: u32,
123 pub var_type: String,
124 #[serde(skip_serializing_if = "Option::is_none")]
125 pub effect_index: Option<u8>,
126}
127
128#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
130#[cfg_attr(feature = "wasm", derive(Tsify))]
131#[serde(rename_all = "camelCase")]
132pub struct CustomVariableNode {
133 var_name: String,
134}
135
136impl CustomVariableNode {
137 pub(crate) fn new(var_name: String) -> Self {
138 Self { var_name }
139 }
140 pub fn var_name(&self) -> &str {
141 &self.var_name
142 }
143}
144
145#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
147#[cfg_attr(feature = "wasm", derive(Tsify))]
148#[serde(rename_all = "camelCase")]
149pub struct AtVariableNode {
150 pub var_type: String,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub spell_id: Option<u32>,
153}
154
155#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
157#[cfg_attr(feature = "wasm", derive(Tsify))]
158#[serde(rename_all = "camelCase")]
159pub struct EnchantVariableNode {
160 var_type: String,
161}
162
163impl EnchantVariableNode {
164 pub(crate) fn new(var_type: String) -> Self {
165 Self { var_type }
166 }
167 pub fn var_type(&self) -> &str {
168 &self.var_type
169 }
170}
171
172#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
174#[cfg_attr(feature = "wasm", derive(Tsify))]
175#[serde(rename_all = "camelCase")]
176pub struct MiscVariableNode {
177 pub var_name: String,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub id: Option<u32>,
180}
181
182#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
184#[cfg_attr(feature = "wasm", derive(Tsify))]
185#[serde(rename_all = "camelCase")]
186pub struct PluralizationNode {
187 pub singular: String,
188 pub plural: String,
189 pub capitalized: bool,
190}
191
192#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
194#[cfg_attr(feature = "wasm", derive(Tsify))]
195#[serde(rename_all = "camelCase")]
196pub struct GenderNode {
197 pub male: String,
198 pub female: String,
199 pub capitalized: bool,
200}
201
202#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
204#[cfg_attr(feature = "wasm", derive(Tsify))]
205#[serde(rename_all = "camelCase")]
206pub struct ExpressionBlockNode {
207 pub expression: ExpressionNode,
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub decimal_places: Option<u8>,
210}
211
212#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
214#[cfg_attr(feature = "wasm", derive(Tsify))]
215#[serde(tag = "exprType", rename_all = "camelCase")]
216pub enum ExpressionNode {
218 Binary(BinaryExpressionNode),
219 Unary(UnaryExpressionNode),
220 FunctionCall(FunctionCallNode),
221 Variable(Box<VariableNode>),
222 Number(NumberLiteralNode),
223 Paren(ParenExpressionNode),
224}
225
226#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
228#[cfg_attr(feature = "wasm", derive(Tsify))]
229#[serde(rename_all = "camelCase")]
230pub struct BinaryExpressionNode {
231 pub left: Box<ExpressionNode>,
233 pub operator: BinaryOperator,
234 pub right: Box<ExpressionNode>,
236}
237
238#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
240#[cfg_attr(feature = "wasm", derive(Tsify))]
241#[serde(rename_all = "camelCase")]
242pub enum BinaryOperator {
244 Add,
245 Sub,
246 Mul,
247 Div,
248}
249
250#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
252#[cfg_attr(feature = "wasm", derive(Tsify))]
253#[serde(rename_all = "camelCase")]
254pub struct UnaryExpressionNode {
255 pub operator: UnaryOperator,
256 pub operand: Box<ExpressionNode>,
258}
259
260#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
262#[cfg_attr(feature = "wasm", derive(Tsify))]
263#[serde(rename_all = "camelCase")]
264pub enum UnaryOperator {
266 Neg,
267}
268
269#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
271#[cfg_attr(feature = "wasm", derive(Tsify))]
272#[serde(rename_all = "camelCase")]
273pub struct FunctionCallNode {
274 pub func_name: String,
275 pub args: Vec<ExpressionNode>,
276}
277
278#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
280#[cfg_attr(feature = "wasm", derive(Tsify))]
281#[serde(rename_all = "camelCase")]
282pub struct NumberLiteralNode {
283 value: f64,
284}
285
286impl NumberLiteralNode {
287 pub(crate) const fn new(value: f64) -> Self {
288 Self { value }
289 }
290 pub const fn value(&self) -> f64 {
291 self.value
292 }
293}
294
295#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
297#[cfg_attr(feature = "wasm", derive(Tsify))]
298#[serde(rename_all = "camelCase")]
299pub struct ParenExpressionNode {
300 pub expression: Box<ExpressionNode>,
302}
303
304#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
306#[cfg_attr(feature = "wasm", derive(Tsify))]
307#[serde(rename_all = "camelCase")]
308pub struct ConditionalNode {
309 pub conditions: Vec<ConditionalBranchNode>,
310 #[serde(skip_serializing_if = "Option::is_none")]
311 pub else_branch: Option<Vec<SpellDescriptionNode>>,
312}
313
314#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
316#[cfg_attr(feature = "wasm", derive(Tsify))]
317#[serde(rename_all = "camelCase")]
318pub struct ConditionalBranchNode {
319 pub predicate: ConditionalPredicateNode,
320 pub content: Vec<SpellDescriptionNode>,
321}
322
323#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
325#[cfg_attr(feature = "wasm", derive(Tsify))]
326#[serde(rename_all = "camelCase")]
327pub struct ConditionalPredicateNode {
328 pub conditions: Vec<SingleConditionNode>,
329}
330
331#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
333#[cfg_attr(feature = "wasm", derive(Tsify))]
334#[serde(tag = "condType", rename_all = "camelCase")]
335pub enum SingleConditionNode {
337 SpellKnown(SpellKnownConditionNode),
338 Aura(AuraConditionNode),
339 Specialization(SpecializationConditionNode),
340 PlayerCondition(PlayerConditionNode),
341 Expression(ExpressionConditionNode),
342}
343
344#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
346#[cfg_attr(feature = "wasm", derive(Tsify))]
347#[serde(rename_all = "camelCase")]
348pub struct SpellKnownConditionNode {
349 spell_id: u32,
350}
351
352impl SpellKnownConditionNode {
353 pub(crate) const fn new(spell_id: u32) -> Self {
354 Self { spell_id }
355 }
356 pub const fn spell_id(&self) -> u32 {
357 self.spell_id
358 }
359}
360
361#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
363#[cfg_attr(feature = "wasm", derive(Tsify))]
364#[serde(rename_all = "camelCase")]
365pub struct AuraConditionNode {
366 aura_id: u32,
367}
368
369impl AuraConditionNode {
370 pub(crate) const fn new(aura_id: u32) -> Self {
371 Self { aura_id }
372 }
373 pub const fn aura_id(&self) -> u32 {
374 self.aura_id
375 }
376}
377
378#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
384#[cfg_attr(feature = "wasm", derive(Tsify))]
385#[serde(rename_all = "camelCase")]
386pub struct SpecializationConditionNode {
387 spec_index: u8,
388}
389
390impl SpecializationConditionNode {
391 pub(crate) const fn new(spec_index: u8) -> Self {
392 Self { spec_index }
393 }
394 pub const fn spec_index(&self) -> u8 {
395 self.spec_index
396 }
397}
398
399#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
401#[cfg_attr(feature = "wasm", derive(Tsify))]
402#[serde(rename_all = "camelCase")]
403pub struct PlayerConditionNode {
404 condition_id: u32,
405}
406
407impl PlayerConditionNode {
408 pub(crate) const fn new(condition_id: u32) -> Self {
409 Self { condition_id }
410 }
411 pub const fn condition_id(&self) -> u32 {
412 self.condition_id
413 }
414}
415
416#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
418#[cfg_attr(feature = "wasm", derive(Tsify))]
419#[serde(rename_all = "camelCase")]
420pub struct ExpressionConditionNode {
422 pub func_name: String,
423 pub args: Vec<ExpressionNode>,
424}