Skip to main content

battler_data/mons/
shiny_chance.rs

1use alloc::format;
2use core::{
3    fmt,
4    str::FromStr,
5};
6
7use anyhow::Error;
8use serde::{
9    Deserialize,
10    Serialize,
11    de::Visitor,
12};
13
14/// The chance that a Mon is shiny.
15#[derive(Debug, Default, Clone, PartialEq)]
16pub enum ShinyChance {
17    /// The Mon cannot be shiny.
18    Never,
19    /// The Mon may be shiny.
20    #[default]
21    Chance,
22    /// The Mon must be shiny.
23    Always,
24}
25
26impl From<bool> for ShinyChance {
27    fn from(value: bool) -> Self {
28        if value { Self::Always } else { Self::Never }
29    }
30}
31
32impl FromStr for ShinyChance {
33    type Err = Error;
34
35    fn from_str(s: &str) -> Result<Self, Self::Err> {
36        match s {
37            "maybe" => Ok(Self::Chance),
38            "always" => Ok(Self::Always),
39            "never" => Ok(Self::Never),
40            _ => Err(Error::msg(format!("invalid shiny chance \"{s}\""))),
41        }
42    }
43}
44
45impl Serialize for ShinyChance {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: serde::Serializer,
49    {
50        match self {
51            Self::Never => serializer.serialize_bool(false),
52            Self::Chance => serializer.serialize_str("maybe"),
53            Self::Always => serializer.serialize_bool(true),
54        }
55    }
56}
57
58struct ShinyChanceVisitor;
59
60impl<'de> Visitor<'de> for ShinyChanceVisitor {
61    type Value = ShinyChance;
62
63    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
64        write!(formatter, "a boolean or \"maybe\"")
65    }
66
67    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
68    where
69        E: serde::de::Error,
70    {
71        Ok(Self::Value::from(v))
72    }
73
74    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
75    where
76        E: serde::de::Error,
77    {
78        Self::Value::from_str(v)
79            .map_err(|_| E::invalid_value(serde::de::Unexpected::Str(&v), &self))
80    }
81}
82
83impl<'de> Deserialize<'de> for ShinyChance {
84    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85    where
86        D: serde::Deserializer<'de>,
87    {
88        deserializer.deserialize_any(ShinyChanceVisitor)
89    }
90}
91
92#[cfg(test)]
93mod shiny_chance_test {
94    use crate::{
95        mons::ShinyChance,
96        test_util::{
97            test_serialization,
98            test_string_deserialization,
99        },
100    };
101
102    #[test]
103    fn serializes_numbers_and_strings() {
104        test_serialization(ShinyChance::Never, false);
105        test_serialization(ShinyChance::Chance, "\"maybe\"");
106        test_serialization(ShinyChance::Always, true);
107    }
108
109    #[test]
110    fn deserializes_alias_strings() {
111        test_string_deserialization("always", ShinyChance::Always);
112        test_string_deserialization("never", ShinyChance::Never);
113    }
114}