Skip to main content

ed_journals/modules/commander/models/
combat_rank.rs

1use std::fmt::{Display, Formatter};
2use std::str::FromStr;
3
4use crate::deserialize_in_order_impl;
5use serde::Serialize;
6use thiserror::Error;
7
8#[derive(Debug, Serialize, Clone, PartialEq)]
9pub enum CombatRank {
10    Harmless,
11    MostlyHarmless,
12    Novice,
13    Competent,
14    Expert,
15    Master,
16    Dangerous,
17    Deadly,
18    Elite,
19    EliteI,
20    EliteII,
21    EliteIII,
22    EliteIV,
23    EliteV,
24
25    #[cfg(feature = "allow-unknown")]
26    #[cfg_attr(docsrs, doc(cfg(feature = "allow-unknown")))]
27    UnknownU8(u8),
28
29    #[cfg(feature = "allow-unknown")]
30    #[cfg_attr(docsrs, doc(cfg(feature = "allow-unknown")))]
31    UnknownString(String),
32}
33
34#[derive(Debug, Error)]
35pub enum CombatRankError {
36    #[error("Unknown combat rank with id '{0}'")]
37    UnknownCombatRank(u8),
38
39    #[error("Unknown combat rank string: '{0}'")]
40    UnknownCombatString(String),
41
42    #[error("Incorrect type used for combat rank")]
43    IncorrectType,
44}
45
46impl TryFrom<u8> for CombatRank {
47    type Error = CombatRankError;
48
49    fn try_from(value: u8) -> Result<Self, Self::Error> {
50        match value {
51            0 => Ok(CombatRank::Harmless),
52            1 => Ok(CombatRank::MostlyHarmless),
53            2 => Ok(CombatRank::Novice),
54            3 => Ok(CombatRank::Competent),
55            4 => Ok(CombatRank::Expert),
56            5 => Ok(CombatRank::Master),
57            6 => Ok(CombatRank::Dangerous),
58            7 => Ok(CombatRank::Deadly),
59            8 => Ok(CombatRank::Elite),
60            9 => Ok(CombatRank::EliteI),
61            10 => Ok(CombatRank::EliteII),
62            11 => Ok(CombatRank::EliteIII),
63            12 => Ok(CombatRank::EliteIV),
64            13 => Ok(CombatRank::EliteV),
65
66            #[cfg(feature = "allow-unknown")]
67            _ => Ok(CombatRank::UnknownU8(value)),
68
69            #[cfg(not(feature = "allow-unknown"))]
70            _ => Err(CombatRankError::UnknownCombatRank(value)),
71        }
72    }
73}
74
75impl FromStr for CombatRank {
76    type Err = CombatRankError;
77
78    fn from_str(s: &str) -> Result<Self, Self::Err> {
79        match s {
80            "Harmless" => Ok(CombatRank::Harmless),
81            "MostlyHarmless" => Ok(CombatRank::MostlyHarmless),
82            "Novice" => Ok(CombatRank::Novice),
83            "Competent" => Ok(CombatRank::Competent),
84            "Expert" => Ok(CombatRank::Expert),
85            "Master" => Ok(CombatRank::Master),
86            "Dangerous" => Ok(CombatRank::Dangerous),
87            "Deadly" => Ok(CombatRank::Deadly),
88            "Elite" => Ok(CombatRank::Elite),
89            "EliteI" => Ok(CombatRank::EliteI),
90            "EliteII" => Ok(CombatRank::EliteII),
91            "EliteIII" => Ok(CombatRank::EliteIII),
92            "EliteIV" => Ok(CombatRank::EliteIV),
93            "EliteV" => Ok(CombatRank::EliteV),
94
95            #[cfg(feature = "allow-unknown")]
96            _ => Ok(CombatRank::UnknownString(s.to_string())),
97
98            #[cfg(not(feature = "allow-unknown"))]
99            _ => Err(CombatRankError::UnknownCombatString(s.to_string())),
100        }
101    }
102}
103
104deserialize_in_order_impl!(
105    CombatRank =>
106        A ? u8,
107        B # String,
108);
109
110// #[derive(Deserialize)]
111// #[serde(untagged)]
112// enum CombatInput {
113//     U8(u8),
114//     String(String),
115// }
116//
117// impl<'de> serde::Deserialize<'de> for CombatRank {
118//     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
119//     where
120//         D: Deserializer<'de>,
121//     {
122//         let input = CombatInput::deserialize(deserializer)?;
123//
124//         match input {
125//             CombatInput::U8(value) => Ok(CombatRank::try_from(value).map_err(|_| {
126//                 serde::de::Error::custom(format!("Failed to deserialize u8: got '{}'", value))
127//             })?),
128//             CombatInput::String(value) => Ok(CombatRank::from_str(&value).map_err(|_| {
129//                 serde::de::Error::custom(format!("Failed to deserialize string: got '{}'", value))
130//             })?),
131//         }
132//     }
133// }
134
135impl Display for CombatRank {
136    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
137        write!(
138            f,
139            "{}",
140            match self {
141                CombatRank::Harmless => "Harmless",
142                CombatRank::MostlyHarmless => "Mostly Harmless",
143                CombatRank::Novice => "Novice",
144                CombatRank::Competent => "Competent",
145                CombatRank::Expert => "Expert",
146                CombatRank::Master => "Master",
147                CombatRank::Dangerous => "Dangerous",
148                CombatRank::Deadly => "Deadly",
149                CombatRank::Elite => "Elite",
150                CombatRank::EliteI => "Elite I",
151                CombatRank::EliteII => "Elite II",
152                CombatRank::EliteIII => "Elite III",
153                CombatRank::EliteIV => "Elite IV",
154                CombatRank::EliteV => "Elite V",
155
156                #[cfg(feature = "allow-unknown")]
157                CombatRank::UnknownU8(unknown) =>
158                    return write!(f, "Unknown combat rank nr: {unknown}"),
159
160                #[cfg(feature = "allow-unknown")]
161                CombatRank::UnknownString(unknown) =>
162                    return write!(f, "Unknown combat rank: {unknown}"),
163            }
164        )
165    }
166}