deepwoken_reqparse/model/
stat.rs1use std::fmt;
2use std::str::FromStr;
3
4use serde::{Deserialize, Deserializer, Serialize, de};
5
6#[repr(u32)]
7#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
8pub enum Stat {
9 Strength = 0,
10 Fortitude = 1,
11 Agility = 2,
12 Intelligence = 3,
13 Willpower = 4,
14 Charisma = 5,
15 HeavyWeapon = 6,
16 MediumWeapon = 7,
17 LightWeapon = 8,
18 Frostdraw = 9,
19 Flamecharm = 10,
20 Thundercall = 11,
21 Galebreathe = 12,
22 Shadowcast = 13,
23 Ironsing = 14,
24 Bloodrend = 15,
25 Total = 16
28}
29
30impl Stat {
31 pub fn from_u32_unchecked(value: u32) -> Self {
32 unsafe { std::mem::transmute(value) }
34 }
35
36 pub fn short_name(&self) -> &'static str {
37 match self {
38 Stat::Strength => "STR",
39 Stat::Fortitude => "FTD",
40 Stat::Agility => "AGL",
41 Stat::Intelligence => "INT",
42 Stat::Willpower => "WLL",
43 Stat::Charisma => "CHA",
44 Stat::HeavyWeapon => "HVY",
45 Stat::MediumWeapon => "MED",
46 Stat::LightWeapon => "LHT",
47 Stat::Frostdraw => "ICE",
48 Stat::Flamecharm => "FLM",
49 Stat::Thundercall => "LTN",
50 Stat::Galebreathe => "WND",
51 Stat::Shadowcast => "SDW",
52 Stat::Ironsing => "MTL",
53 Stat::Bloodrend => "BLD",
54 Stat::Total => "TTL",
55 }
56 }
57
58 pub fn name(&self) -> &'static str {
59 match self {
60 Stat::Strength => "Strength",
61 Stat::Fortitude => "Fortitude",
62 Stat::Agility => "Agility",
63 Stat::Intelligence => "Intelligence",
64 Stat::Willpower => "Willpower",
65 Stat::Charisma => "Charisma",
66 Stat::HeavyWeapon => "Heavy Wep.",
67 Stat::MediumWeapon => "Medium Wep.",
68 Stat::LightWeapon => "Light Wep.",
69 Stat::Frostdraw => "Frostdraw",
70 Stat::Flamecharm => "Flamecharm",
71 Stat::Thundercall => "Thundercall",
72 Stat::Galebreathe => "Galebreathe",
73 Stat::Shadowcast => "Shadowcast",
74 Stat::Ironsing => "Ironsing",
75 Stat::Bloodrend => "Bloodrend",
76 Stat::Total => "Total",
77 }
78 }
79
80 pub fn from_name(name: &str) -> Option<Self> {
81 let name = name.to_uppercase();
82 match name.as_str() {
83 "STRENGTH" => Some(Stat::Strength),
84 "FORTITUDE" => Some(Stat::Fortitude),
85 "AGILITY" => Some(Stat::Agility),
86 "INTELLIGENCE" => Some(Stat::Intelligence),
87 "WILLPOWER" => Some(Stat::Willpower),
88 "CHARISMA" => Some(Stat::Charisma),
89 "HEAVY WEP." | "HEAVY" => Some(Stat::HeavyWeapon),
90 "MEDIUM WEP." | "MEDIUM" => Some(Stat::MediumWeapon),
91 "LIGHT WEP." | "LIGHT" => Some(Stat::LightWeapon),
92 "FROSTDRAW" => Some(Stat::Frostdraw),
93 "FLAMECHARM" => Some(Stat::Flamecharm),
94 "THUNDERCALL" => Some(Stat::Thundercall),
95 "GALEBREATHE" => Some(Stat::Galebreathe),
96 "SHADOWCAST" => Some(Stat::Shadowcast),
97 "IRONSING" => Some(Stat::Ironsing),
98 "BLOODREND" => Some(Stat::Bloodrend),
99 "TOTAL" => Some(Stat::Total),
100 _ => None,
101 }
102 }
103
104 pub fn from_short_name(short: &str) -> Option<Self> {
105 let short = short.to_uppercase();
106
107 match short.as_str() {
108 "STR" => Some(Stat::Strength),
109 "FTD" => Some(Stat::Fortitude),
110 "AGL" | "AGI" => Some(Stat::Agility),
111 "INT" => Some(Stat::Intelligence),
112 "WLL" | "WIL" => Some(Stat::Willpower),
114 "CHA" => Some(Stat::Charisma),
115 "HVY" => Some(Stat::HeavyWeapon),
116 "MED" => Some(Stat::MediumWeapon),
117 "LHT" => Some(Stat::LightWeapon),
118 "ICE" => Some(Stat::Frostdraw),
119 "FLM" | "FIR" => Some(Stat::Flamecharm),
120 "LTN" => Some(Stat::Thundercall),
121 "WND" => Some(Stat::Galebreathe),
122 "SDW" => Some(Stat::Shadowcast),
123 "MTL" => Some(Stat::Ironsing),
124 "BLD" => Some(Stat::Bloodrend),
125 "TTL" | "TOT" => Some(Stat::Total),
126 _ => None,
127 }
128 }
129
130 pub const fn is_attunement(&self) -> bool {
131 match self {
132 Stat::Frostdraw | Stat::Flamecharm | Stat::Thundercall
133 | Stat::Galebreathe | Stat::Shadowcast | Stat::Ironsing
134 | Stat::Bloodrend => true,
135 _ => false,
136 }
137 }
138
139 pub const fn as_u32(self) -> u32 {
140 self as u32
141 }
142
143 pub const fn as_i64(self) -> i64 {
144 self as i64
145 }
146}
147
148impl From<Stat> for u32 {
149 fn from(stat: Stat) -> u32 {
150 stat as u32
151 }
152}
153
154impl From<Stat> for i64 {
155 fn from(stat: Stat) -> i64 {
156 stat as i64
157 }
158}
159
160impl TryFrom<u32> for Stat {
161 type Error = &'static str;
162
163 fn try_from(value: u32) -> Result<Self, Self::Error> {
164 match value {
165 0 => Ok(Stat::Strength),
166 1 => Ok(Stat::Fortitude),
167 2 => Ok(Stat::Agility),
168 3 => Ok(Stat::Intelligence),
169 4 => Ok(Stat::Willpower),
170 5 => Ok(Stat::Charisma),
171 6 => Ok(Stat::HeavyWeapon),
172 7 => Ok(Stat::MediumWeapon),
173 8 => Ok(Stat::LightWeapon),
174 9 => Ok(Stat::Frostdraw),
175 10 => Ok(Stat::Flamecharm),
176 11 => Ok(Stat::Thundercall),
177 12 => Ok(Stat::Galebreathe),
178 13 => Ok(Stat::Shadowcast),
179 14 => Ok(Stat::Ironsing),
180 15 => Ok(Stat::Bloodrend),
181 _ => Err("Invalid stat id"),
182 }
183 }
184}
185
186impl TryFrom<i64> for Stat {
187 type Error = &'static str;
188
189 fn try_from(value: i64) -> Result<Self, Self::Error> {
190 if value < 0 {
191 return Err("Stat id cannot be negative");
192 }
193 (value as u32).try_into()
194 }
195}
196
197impl FromStr for Stat {
198 type Err = &'static str;
199
200 fn from_str(s: &str) -> Result<Self, Self::Err> {
201 Self::from_short_name(s)
202 .or_else(|| Self::from_name(s))
203 .ok_or("Invalid stat name or abbreviation")
204 }
205}
206
207impl fmt::Debug for Stat {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 write!(f, "{}", self.name())
210 }
211}
212
213impl fmt::Display for Stat {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 write!(f, "{}", self.name())
216 }
217}
218
219impl From<Stat> for String {
220 fn from(stat: Stat) -> String {
221 stat.name().to_string()
222 }
223}
224
225impl<'de> Deserialize<'de> for Stat {
226 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227 where
228 D: Deserializer<'de>,
229 {
230 let s = String::deserialize(deserializer)?;
231 s.parse().map_err(de::Error::custom)
233 }
234}
235
236impl Serialize for Stat {
237 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
238 where
239 S: serde::Serializer,
240 {
241 serializer.serialize_str(self.name())
242 }
243}