Skip to main content

battler_data/moves/
ohko_type.rs

1use core::{
2    fmt,
3    fmt::Display,
4    str::FromStr,
5};
6
7use anyhow::Error;
8use serde::{
9    Deserialize,
10    Serialize,
11    Serializer,
12    de::{
13        Unexpected,
14        Visitor,
15    },
16};
17
18use crate::Type;
19
20/// The type of one-hit KO dealt by the move.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum OhkoType {
23    /// OHKOs any target.
24    Always,
25    /// OHKOs targets of the given type.
26    Type(Type),
27}
28
29impl Display for OhkoType {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        match self {
32            Self::Always => write!(f, "{}", true),
33            Self::Type(typ) => write!(f, "{typ}"),
34        }
35    }
36}
37
38impl FromStr for OhkoType {
39    type Err = Error;
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        Ok(OhkoType::Type(Type::from_str(s).map_err(Error::msg)?))
42    }
43}
44
45impl Serialize for OhkoType {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: Serializer,
49    {
50        match self {
51            Self::Always => serializer.serialize_bool(true),
52            Self::Type(typ) => typ.serialize(serializer),
53        }
54    }
55}
56
57struct OhkoTypeVisitor;
58
59impl<'de> Visitor<'de> for OhkoTypeVisitor {
60    type Value = OhkoType;
61
62    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
63        write!(formatter, "true or \"level\"")
64    }
65
66    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
67    where
68        E: serde::de::Error,
69    {
70        if !v {
71            Err(E::invalid_value(Unexpected::Bool(v), &self))
72        } else {
73            Ok(Self::Value::Always)
74        }
75    }
76
77    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
78    where
79        E: serde::de::Error,
80    {
81        Self::Value::from_str(v).map_err(|_| E::invalid_value(Unexpected::Str(&v), &self))
82    }
83}
84
85impl<'de> Deserialize<'de> for OhkoType {
86    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87    where
88        D: serde::Deserializer<'de>,
89    {
90        deserializer.deserialize_any(OhkoTypeVisitor)
91    }
92}
93
94#[cfg(test)]
95mod ohko_type_test {
96    use crate::{
97        mons::Type,
98        moves::OhkoType,
99        test_util::test_serialization,
100    };
101
102    #[test]
103    fn serializes_to_string() {
104        test_serialization(OhkoType::Always, true);
105        test_serialization(OhkoType::Type(Type::Ice), "\"Ice\"");
106    }
107}