1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum ApiType {
12 Abandon,
13 ActivateAbility,
14 AddOrRemoveCounter,
15 AddPhase,
16 AddTurn,
17 AdvanceCrank,
18 Airbend,
19 AlterAttribute,
20 Amass,
21 Animate,
22 AnimateAll,
23 Attach,
24 Ascend,
25 AssembleContraption,
26 AssignGroup,
27 Balance,
28 BecomeMonarch,
29 BecomesBlocked,
30 BidLife,
31 Blight,
32 Block,
33 Bond,
34 Branch,
35 Camouflage,
36 ChangeCombatants,
37 ChangeSpeed,
38 ChangeTargets,
39 ChangeText,
40 ChangeX,
41 ChangeZone,
42 ChangeZoneAll,
43 ChaosEnsues,
44 Charm,
45 ChooseCard,
46 ChooseCardName,
47 ChooseColor,
48 ChooseDirection,
49 ChooseEvenOdd,
50 ChooseGeneric,
51 ChooseNumber,
52 ChoosePlayer,
53 ChooseSector,
54 ChooseSource,
55 ChooseType,
56 ClaimThePrize,
57 Clash,
58 ClassLevelUp,
59 Cleanup,
60 Cloak,
61 Clone,
62 Connive,
63 CopyPermanent,
64 CopySpellAbility,
65 ControlSpell,
66 ControlPlayer,
67 Counter,
68 CountersMove,
69 CountersNote,
70 DamageAll,
71 DamagePrevent,
72 DealDamage,
73 Detain,
74 DayTime,
75 Debuff,
76 DelayedTrigger,
77 Destroy,
78 DestroyAll,
79 Dig,
80 DigMultiple,
81 DigUntil,
82 Discard,
83 Discover,
84 DrainMana,
85 Draft,
86 Draw,
87 EachDamage,
88 Earthbend,
89 Effect,
90 Encode,
91 EndCombatPhase,
92 EndTurn,
93 Endure,
94 ExchangeLife,
95 ExchangeLifeVariant,
96 ExchangeControl,
97 ExchangeControlVariant,
98 ExchangePower,
99 ExchangeZone,
100 ExchangeTextBox,
101 Explore,
102 Fight,
103 FlipACoin,
104 FlipOntoBattlefield,
105 Fog,
106 GainControl,
107 GainControlVariant,
108 GainLife,
109 GainOwnership,
110 GameDrawn,
111 GenericChoice,
112 Goad,
113 Haunt,
114 Heist,
115 Investigate,
116 Intensify,
117 ImmediateTrigger,
118 Incubate,
119 Learn,
120 LookAt,
121 LoseLife,
122 LosePerpetual,
123 LosesGame,
124 MakeCard,
125 Mana,
126 ManaReflected,
127 Manifest,
128 ManifestDread,
129 Meld,
130 Mill,
131 MoveCounter,
132 MultiplePiles,
133 MultiplyCounter,
134 MustBlock,
135 Mutate,
136 NameCard,
137 OpenAttraction,
138 PeekAndReveal,
139 PermanentCreature,
140 PermanentNoncreature,
141 Phases,
142 Planeswalk,
143 Play,
144 PlayLandVariant,
145 Poison,
146 PreventDamage,
147 Proliferate,
148 Protection,
149 ProtectionAll,
150 Pump,
151 PumpAll,
152 PutCounter,
153 PutCounterAll,
154 Radiation,
155 RearrangeTopOfLibrary,
156 Regenerate,
157 Regeneration,
158 RemoveCounter,
159 RemoveCounterAll,
160 RemoveFromCombat,
161 RemoveFromGame,
162 RemoveFromMatch,
163 ReorderZone,
164 Repeat,
165 RepeatEach,
166 ReplaceCounter,
167 ReplaceEffect,
168 ReplaceMana,
169 ReplaceDamage,
170 ReplaceToken,
171 ReplaceSplitDamage,
172 RestartGame,
173 Reveal,
174 RevealHand,
175 ReverseTurnOrder,
176 RingTemptsYou,
177 RollDice,
178 RollPlanarDice,
179 RunChaos,
180 Sacrifice,
181 SacrificeAll,
182 Scry,
183 Seek,
184 SetInMotion,
185 SetLife,
186 SetState,
187 Shuffle,
188 SkipPhase,
189 SkipTurn,
190 StoreSVar,
191 Subgame,
192 Surveil,
193 SwitchBlock,
194 TakeInitiative,
195 Tap,
196 TapAll,
197 TapOrUntap,
198 TapOrUntapAll,
199 TimeTravel,
200 Token,
201 TwoPiles,
202 Unattach,
203 UnlockDoor,
204 Untap,
205 UntapAll,
206 Venture,
207 VillainousChoice,
208 Vote,
209 WinsGame,
210 ZoneExchange,
211 BlankLine,
213 DamageResolve,
214 ChangeZoneResolve,
215 CompanionChoose,
216 InternalLegendaryRule,
217 InternalIgnoreEffect,
218 InternalRadiation,
219 Plot,
220}
221
222impl ApiType {
223 pub fn smart_value_of(value: &str) -> Option<ApiType> {
226 let lower = value.to_ascii_lowercase();
227 ALL_API_TYPES
228 .iter()
229 .find(|(name, _)| name.to_ascii_lowercase() == lower)
230 .map(|(_, api)| *api)
231 }
232
233 pub fn name(&self) -> &'static str {
235 ALL_API_TYPES
236 .iter()
237 .find(|(_, api)| api == self)
238 .map(|(name, _)| *name)
239 .unwrap_or("Unknown")
240 }
241}
242
243impl std::fmt::Display for ApiType {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 f.write_str(self.name())
246 }
247}
248
249const ALL_API_TYPES: &[(&str, ApiType)] = &[
253 ("Abandon", ApiType::Abandon),
254 ("ActivateAbility", ApiType::ActivateAbility),
255 ("AddOrRemoveCounter", ApiType::AddOrRemoveCounter),
256 ("AddPhase", ApiType::AddPhase),
257 ("AddTurn", ApiType::AddTurn),
258 ("AdvanceCrank", ApiType::AdvanceCrank),
259 ("Airbend", ApiType::Airbend),
260 ("AlterAttribute", ApiType::AlterAttribute),
261 ("Amass", ApiType::Amass),
262 ("Animate", ApiType::Animate),
263 ("AnimateAll", ApiType::AnimateAll),
264 ("Attach", ApiType::Attach),
265 ("Ascend", ApiType::Ascend),
266 ("AssembleContraption", ApiType::AssembleContraption),
267 ("AssignGroup", ApiType::AssignGroup),
268 ("Balance", ApiType::Balance),
269 ("BecomeMonarch", ApiType::BecomeMonarch),
270 ("BecomesBlocked", ApiType::BecomesBlocked),
271 ("BidLife", ApiType::BidLife),
272 ("Blight", ApiType::Blight),
273 ("Block", ApiType::Block),
274 ("Bond", ApiType::Bond),
275 ("Branch", ApiType::Branch),
276 ("Camouflage", ApiType::Camouflage),
277 ("ChangeCombatants", ApiType::ChangeCombatants),
278 ("ChangeSpeed", ApiType::ChangeSpeed),
279 ("ChangeTargets", ApiType::ChangeTargets),
280 ("ChangeText", ApiType::ChangeText),
281 ("ChangeX", ApiType::ChangeX),
282 ("ChangeZone", ApiType::ChangeZone),
283 ("ChangeZoneAll", ApiType::ChangeZoneAll),
284 ("ChaosEnsues", ApiType::ChaosEnsues),
285 ("Charm", ApiType::Charm),
286 ("ChooseCard", ApiType::ChooseCard),
287 ("ChooseCardName", ApiType::ChooseCardName),
288 ("ChooseColor", ApiType::ChooseColor),
289 ("ChooseDirection", ApiType::ChooseDirection),
290 ("ChooseEvenOdd", ApiType::ChooseEvenOdd),
291 ("ChooseGeneric", ApiType::ChooseGeneric),
292 ("ChooseNumber", ApiType::ChooseNumber),
293 ("ChoosePlayer", ApiType::ChoosePlayer),
294 ("ChooseSector", ApiType::ChooseSector),
295 ("ChooseSource", ApiType::ChooseSource),
296 ("ChooseType", ApiType::ChooseType),
297 ("ClaimThePrize", ApiType::ClaimThePrize),
298 ("Clash", ApiType::Clash),
299 ("ClassLevelUp", ApiType::ClassLevelUp),
300 ("Cleanup", ApiType::Cleanup),
301 ("Cloak", ApiType::Cloak),
302 ("Clone", ApiType::Clone),
303 ("Connive", ApiType::Connive),
304 ("CopyPermanent", ApiType::CopyPermanent),
305 ("CopySpellAbility", ApiType::CopySpellAbility),
306 ("ControlSpell", ApiType::ControlSpell),
307 ("ControlPlayer", ApiType::ControlPlayer),
308 ("Counter", ApiType::Counter),
309 ("CountersMove", ApiType::CountersMove),
310 ("CountersNote", ApiType::CountersNote),
311 ("DamageAll", ApiType::DamageAll),
312 ("DamagePrevent", ApiType::DamagePrevent),
313 ("DealDamage", ApiType::DealDamage),
314 ("Detain", ApiType::Detain),
315 ("DayTime", ApiType::DayTime),
316 ("Debuff", ApiType::Debuff),
317 ("DelayedTrigger", ApiType::DelayedTrigger),
318 ("Destroy", ApiType::Destroy),
319 ("DestroyAll", ApiType::DestroyAll),
320 ("Dig", ApiType::Dig),
321 ("DigMultiple", ApiType::DigMultiple),
322 ("DigUntil", ApiType::DigUntil),
323 ("Discard", ApiType::Discard),
324 ("Discover", ApiType::Discover),
325 ("DrainMana", ApiType::DrainMana),
326 ("Draft", ApiType::Draft),
327 ("Draw", ApiType::Draw),
328 ("EachDamage", ApiType::EachDamage),
329 ("Earthbend", ApiType::Earthbend),
330 ("Effect", ApiType::Effect),
331 ("Encode", ApiType::Encode),
332 ("EndCombatPhase", ApiType::EndCombatPhase),
333 ("EndTurn", ApiType::EndTurn),
334 ("Endure", ApiType::Endure),
335 ("ExchangeLife", ApiType::ExchangeLife),
336 ("ExchangeLifeVariant", ApiType::ExchangeLifeVariant),
337 ("ExchangeControl", ApiType::ExchangeControl),
338 ("ExchangeControlVariant", ApiType::ExchangeControlVariant),
339 ("ExchangePower", ApiType::ExchangePower),
340 ("ExchangeZone", ApiType::ExchangeZone),
341 ("ExchangeTextBox", ApiType::ExchangeTextBox),
342 ("Explore", ApiType::Explore),
343 ("Fight", ApiType::Fight),
344 ("FlipACoin", ApiType::FlipACoin),
345 ("FlipOntoBattlefield", ApiType::FlipOntoBattlefield),
346 ("Fog", ApiType::Fog),
347 ("GainControl", ApiType::GainControl),
348 ("GainControlVariant", ApiType::GainControlVariant),
349 ("GainLife", ApiType::GainLife),
350 ("GainOwnership", ApiType::GainOwnership),
351 ("GameDrawn", ApiType::GameDrawn),
352 ("GenericChoice", ApiType::GenericChoice),
353 ("Goad", ApiType::Goad),
354 ("Haunt", ApiType::Haunt),
355 ("Heist", ApiType::Heist),
356 ("Investigate", ApiType::Investigate),
357 ("Intensify", ApiType::Intensify),
358 ("ImmediateTrigger", ApiType::ImmediateTrigger),
359 ("Incubate", ApiType::Incubate),
360 ("Learn", ApiType::Learn),
361 ("LookAt", ApiType::LookAt),
362 ("LoseLife", ApiType::LoseLife),
363 ("LosePerpetual", ApiType::LosePerpetual),
364 ("LosesGame", ApiType::LosesGame),
365 ("MakeCard", ApiType::MakeCard),
366 ("Mana", ApiType::Mana),
367 ("ManaReflected", ApiType::ManaReflected),
368 ("Manifest", ApiType::Manifest),
369 ("ManifestDread", ApiType::ManifestDread),
370 ("Meld", ApiType::Meld),
371 ("Mill", ApiType::Mill),
372 ("MoveCounter", ApiType::MoveCounter),
373 ("MultiplePiles", ApiType::MultiplePiles),
374 ("MultiplyCounter", ApiType::MultiplyCounter),
375 ("MustBlock", ApiType::MustBlock),
376 ("Mutate", ApiType::Mutate),
377 ("NameCard", ApiType::NameCard),
378 ("OpenAttraction", ApiType::OpenAttraction),
379 ("PeekAndReveal", ApiType::PeekAndReveal),
380 ("PermanentCreature", ApiType::PermanentCreature),
381 ("PermanentNoncreature", ApiType::PermanentNoncreature),
382 ("Phases", ApiType::Phases),
383 ("Planeswalk", ApiType::Planeswalk),
384 ("Play", ApiType::Play),
385 ("PlayLandVariant", ApiType::PlayLandVariant),
386 ("Plot", ApiType::Plot),
387 ("Poison", ApiType::Poison),
388 ("PreventDamage", ApiType::PreventDamage),
389 ("Proliferate", ApiType::Proliferate),
390 ("Protection", ApiType::Protection),
391 ("ProtectionAll", ApiType::ProtectionAll),
392 ("Pump", ApiType::Pump),
393 ("PumpAll", ApiType::PumpAll),
394 ("PutCounter", ApiType::PutCounter),
395 ("PutCounterAll", ApiType::PutCounterAll),
396 ("Radiation", ApiType::Radiation),
397 ("RearrangeTopOfLibrary", ApiType::RearrangeTopOfLibrary),
398 ("Regenerate", ApiType::Regenerate),
399 ("Regeneration", ApiType::Regeneration),
400 ("RemoveCounter", ApiType::RemoveCounter),
401 ("RemoveCounterAll", ApiType::RemoveCounterAll),
402 ("RemoveFromCombat", ApiType::RemoveFromCombat),
403 ("RemoveFromGame", ApiType::RemoveFromGame),
404 ("RemoveFromMatch", ApiType::RemoveFromMatch),
405 ("ReorderZone", ApiType::ReorderZone),
406 ("Repeat", ApiType::Repeat),
407 ("RepeatEach", ApiType::RepeatEach),
408 ("ReplaceCounter", ApiType::ReplaceCounter),
409 ("ReplaceEffect", ApiType::ReplaceEffect),
410 ("ReplaceMana", ApiType::ReplaceMana),
411 ("ReplaceDamage", ApiType::ReplaceDamage),
412 ("ReplaceToken", ApiType::ReplaceToken),
413 ("ReplaceSplitDamage", ApiType::ReplaceSplitDamage),
414 ("RestartGame", ApiType::RestartGame),
415 ("Reveal", ApiType::Reveal),
416 ("RevealHand", ApiType::RevealHand),
417 ("ReverseTurnOrder", ApiType::ReverseTurnOrder),
418 ("RingTemptsYou", ApiType::RingTemptsYou),
419 ("RollDice", ApiType::RollDice),
420 ("RollPlanarDice", ApiType::RollPlanarDice),
421 ("RunChaos", ApiType::RunChaos),
422 ("Sacrifice", ApiType::Sacrifice),
423 ("SacrificeAll", ApiType::SacrificeAll),
424 ("Scry", ApiType::Scry),
425 ("Seek", ApiType::Seek),
426 ("SetInMotion", ApiType::SetInMotion),
427 ("SetLife", ApiType::SetLife),
428 ("SetState", ApiType::SetState),
429 ("Shuffle", ApiType::Shuffle),
430 ("SkipPhase", ApiType::SkipPhase),
431 ("SkipTurn", ApiType::SkipTurn),
432 ("StoreSVar", ApiType::StoreSVar),
433 ("Subgame", ApiType::Subgame),
434 ("Surveil", ApiType::Surveil),
435 ("SwitchBlock", ApiType::SwitchBlock),
436 ("TakeInitiative", ApiType::TakeInitiative),
437 ("Tap", ApiType::Tap),
438 ("TapAll", ApiType::TapAll),
439 ("TapOrUntap", ApiType::TapOrUntap),
440 ("TapOrUntapAll", ApiType::TapOrUntapAll),
441 ("TimeTravel", ApiType::TimeTravel),
442 ("Token", ApiType::Token),
443 ("TwoPiles", ApiType::TwoPiles),
444 ("Unattach", ApiType::Unattach),
445 ("UnlockDoor", ApiType::UnlockDoor),
446 ("Untap", ApiType::Untap),
447 ("UntapAll", ApiType::UntapAll),
448 ("Venture", ApiType::Venture),
449 ("VillainousChoice", ApiType::VillainousChoice),
450 ("Vote", ApiType::Vote),
451 ("WinsGame", ApiType::WinsGame),
452 ("ZoneExchange", ApiType::ZoneExchange),
453 ("BlankLine", ApiType::BlankLine),
455 ("DamageResolve", ApiType::DamageResolve),
456 ("ChangeZoneResolve", ApiType::ChangeZoneResolve),
457 ("CompanionChoose", ApiType::CompanionChoose),
458 ("InternalLegendaryRule", ApiType::InternalLegendaryRule),
459 ("InternalIgnoreEffect", ApiType::InternalIgnoreEffect),
460 ("InternalRadiation", ApiType::InternalRadiation),
461 ("ControlExchange", ApiType::ExchangeControl),
463 ("ControlGain", ApiType::GainControl),
464 ("ControlGainVariant", ApiType::GainControlVariant),
465 ("LifeSet", ApiType::SetLife),
466 ("LifeExchange", ApiType::ExchangeLife),
467 ("LifeExchangeVariant", ApiType::ExchangeLifeVariant),
468 ("GameWin", ApiType::WinsGame),
469 ("GameLoss", ApiType::LosesGame),
470 ("GameDraw", ApiType::GameDrawn),
471 ("RingTempts", ApiType::RingTemptsYou),
472 ("TaporUntapAll", ApiType::TapOrUntapAll),
473 ("CountersMultiply", ApiType::MultiplyCounter),
474 ("CountersRemoveAll", ApiType::RemoveCounterAll),
475 ("CountersPutOrRemove", ApiType::AddOrRemoveCounter),
476 ("PowerExchange", ApiType::ExchangePower),
477 ("TextBoxExchange", ApiType::ExchangeTextBox),
478 ("Replace", ApiType::ReplaceEffect),
479];
480
481#[cfg(test)]
482mod tests {
483 use super::*;
484
485 #[test]
486 fn smart_value_of_basic() {
487 assert_eq!(
488 ApiType::smart_value_of("DealDamage"),
489 Some(ApiType::DealDamage)
490 );
491 assert_eq!(
492 ApiType::smart_value_of("dealdamage"),
493 Some(ApiType::DealDamage)
494 );
495 assert_eq!(
496 ApiType::smart_value_of("DEALDAMAGE"),
497 Some(ApiType::DealDamage)
498 );
499 }
500
501 #[test]
502 fn smart_value_of_unknown() {
503 assert_eq!(ApiType::smart_value_of("NotAnApi"), None);
504 }
505
506 #[test]
507 fn name_roundtrip() {
508 let api = ApiType::GainLife;
509 assert_eq!(ApiType::smart_value_of(api.name()), Some(api));
510 }
511
512 #[test]
513 fn alias_resolution() {
514 assert_eq!(
515 ApiType::smart_value_of("ControlGain"),
516 Some(ApiType::GainControl)
517 );
518 assert_eq!(ApiType::smart_value_of("LifeSet"), Some(ApiType::SetLife));
519 assert_eq!(ApiType::smart_value_of("GameWin"), Some(ApiType::WinsGame));
520 assert_eq!(
521 ApiType::smart_value_of("RingTempts"),
522 Some(ApiType::RingTemptsYou)
523 );
524 assert_eq!(
525 ApiType::smart_value_of("TaporUntapAll"),
526 Some(ApiType::TapOrUntapAll)
527 );
528 assert_eq!(
529 ApiType::smart_value_of("Replace"),
530 Some(ApiType::ReplaceEffect)
531 );
532 }
533}