battler_data/moves/
accuracy.rs1use alloc::format;
2use core::{
3 fmt,
4 str::FromStr,
5};
6
7use anyhow::Error;
8use serde::{
9 Deserialize,
10 Serialize,
11 Serializer,
12 de::Visitor,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum Accuracy {
18 Chance(u8),
20 Exempt,
22}
23
24impl Accuracy {
25 pub fn percentage(&self) -> Option<u8> {
26 match self {
27 Self::Chance(n) => Some(*n),
28 Self::Exempt => None,
29 }
30 }
31}
32
33impl Default for Accuracy {
34 fn default() -> Self {
35 Self::Chance(100)
36 }
37}
38
39impl From<u8> for Accuracy {
40 fn from(value: u8) -> Self {
41 Self::Chance(value)
42 }
43}
44
45impl FromStr for Accuracy {
46 type Err = Error;
47
48 fn from_str(s: &str) -> Result<Self, Self::Err> {
49 match s {
50 "exempt" => Ok(Self::Exempt),
51 _ => Err(Error::msg(format!("invalid accuracy \"{s}\""))),
52 }
53 }
54}
55
56impl Serialize for Accuracy {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: Serializer,
60 {
61 match self {
62 Self::Chance(n) => serializer.serialize_u8(*n),
63 Self::Exempt => serializer.collect_str("exempt"),
64 }
65 }
66}
67
68struct AccuracyVisitor;
69
70impl<'de> Visitor<'de> for AccuracyVisitor {
71 type Value = Accuracy;
72
73 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
74 write!(formatter, "an integer or \"exempt\"")
75 }
76
77 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
78 where
79 E: serde::de::Error,
80 {
81 Ok(Self::Value::from(v))
82 }
83
84 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
85 where
86 E: serde::de::Error,
87 {
88 Ok(Self::Value::from(v as u8))
89 }
90
91 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
92 where
93 E: serde::de::Error,
94 {
95 Self::Value::from_str(v)
96 .map_err(|_| E::invalid_value(serde::de::Unexpected::Str(&v), &self))
97 }
98}
99
100impl<'de> Deserialize<'de> for Accuracy {
101 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
102 where
103 D: serde::Deserializer<'de>,
104 {
105 deserializer.deserialize_any(AccuracyVisitor)
106 }
107}
108
109#[cfg(test)]
110mod accuracy_test {
111 use crate::{
112 moves::Accuracy,
113 test_util::test_serialization,
114 };
115
116 #[test]
117 fn serializes_numbers_and_strings() {
118 test_serialization(Accuracy::Chance(100), 100);
119 test_serialization(Accuracy::Chance(50), 50);
120 test_serialization(Accuracy::Exempt, "\"exempt\"");
121 }
122}