1use core::fmt;
4
5use crate::custom_bodies::{CustomBodyId, CustomDefinitionValidationError};
6
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
10#[non_exhaustive]
11pub enum CelestialBodyClass {
12 Luminary,
14 MajorPlanet,
16 LunarPoint,
18 BuiltInAsteroid,
20 Fictitious,
23 Custom,
25}
26
27impl CelestialBodyClass {
28 pub const fn label(self) -> &'static str {
30 match self {
31 Self::Luminary => "luminary",
32 Self::MajorPlanet => "major planet",
33 Self::LunarPoint => "lunar point",
34 Self::BuiltInAsteroid => "built-in asteroid",
35 Self::Fictitious => "fictitious body",
36 Self::Custom => "custom body",
37 }
38 }
39}
40
41impl fmt::Display for CelestialBodyClass {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.write_str(self.label())
44 }
45}
46
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49#[derive(Clone, Debug, PartialEq, Eq, Hash)]
50#[non_exhaustive]
51pub enum CelestialBody {
52 Sun,
54 Moon,
56 Mercury,
58 Venus,
60 Mars,
62 Jupiter,
64 Saturn,
66 Uranus,
68 Neptune,
70 Pluto,
72 MeanNode,
74 TrueNode,
76 MeanApogee,
78 TrueApogee,
80 MeanPerigee,
82 TruePerigee,
84 Ceres,
86 Pallas,
88 Juno,
90 Vesta,
92 Cupido,
94 Hades,
96 Zeus,
98 Kronos,
100 Apollon,
102 Admetos,
104 Vulkanus,
106 Poseidon,
108 Transpluto,
110 Nibiru,
112 Harrington,
114 NeptuneLeverrier,
116 NeptuneAdams,
118 PlutoLowell,
120 PlutoPickering,
122 Vulcan,
124 WhiteMoon,
126 Proserpina,
128 Waldemath,
130 Custom(CustomBodyId),
132}
133
134impl CelestialBody {
135 pub const fn class(&self) -> CelestialBodyClass {
137 match self {
138 Self::Sun | Self::Moon => CelestialBodyClass::Luminary,
139 Self::Mercury
140 | Self::Venus
141 | Self::Mars
142 | Self::Jupiter
143 | Self::Saturn
144 | Self::Uranus
145 | Self::Neptune
146 | Self::Pluto => CelestialBodyClass::MajorPlanet,
147 Self::MeanNode
148 | Self::TrueNode
149 | Self::MeanApogee
150 | Self::TrueApogee
151 | Self::MeanPerigee
152 | Self::TruePerigee => CelestialBodyClass::LunarPoint,
153 Self::Ceres | Self::Pallas | Self::Juno | Self::Vesta => {
154 CelestialBodyClass::BuiltInAsteroid
155 }
156 Self::Cupido
157 | Self::Hades
158 | Self::Zeus
159 | Self::Kronos
160 | Self::Apollon
161 | Self::Admetos
162 | Self::Vulkanus
163 | Self::Poseidon
164 | Self::Transpluto
165 | Self::Nibiru
166 | Self::Harrington
167 | Self::NeptuneLeverrier
168 | Self::NeptuneAdams
169 | Self::PlutoLowell
170 | Self::PlutoPickering
171 | Self::Vulcan
172 | Self::WhiteMoon
173 | Self::Proserpina
174 | Self::Waldemath => CelestialBodyClass::Fictitious,
175 Self::Custom(_) => CelestialBodyClass::Custom,
176 }
177 }
178
179 pub const fn built_in_name(&self) -> Option<&'static str> {
181 match self {
182 Self::Sun => Some("Sun"),
183 Self::Moon => Some("Moon"),
184 Self::Mercury => Some("Mercury"),
185 Self::Venus => Some("Venus"),
186 Self::Mars => Some("Mars"),
187 Self::Jupiter => Some("Jupiter"),
188 Self::Saturn => Some("Saturn"),
189 Self::Uranus => Some("Uranus"),
190 Self::Neptune => Some("Neptune"),
191 Self::Pluto => Some("Pluto"),
192 Self::MeanNode => Some("Mean Node"),
193 Self::TrueNode => Some("True Node"),
194 Self::MeanApogee => Some("Mean Apogee"),
195 Self::TrueApogee => Some("True Apogee"),
196 Self::MeanPerigee => Some("Mean Perigee"),
197 Self::TruePerigee => Some("True Perigee"),
198 Self::Ceres => Some("Ceres"),
199 Self::Pallas => Some("Pallas"),
200 Self::Juno => Some("Juno"),
201 Self::Vesta => Some("Vesta"),
202 Self::Cupido => Some("Cupido"),
203 Self::Hades => Some("Hades"),
204 Self::Zeus => Some("Zeus"),
205 Self::Kronos => Some("Kronos"),
206 Self::Apollon => Some("Apollon"),
207 Self::Admetos => Some("Admetos"),
208 Self::Vulkanus => Some("Vulkanus"),
209 Self::Poseidon => Some("Poseidon"),
210 Self::Transpluto => Some("Transpluto"),
211 Self::Nibiru => Some("Nibiru"),
212 Self::Harrington => Some("Harrington"),
213 Self::NeptuneLeverrier => Some("Neptune (Leverrier)"),
214 Self::NeptuneAdams => Some("Neptune (Adams)"),
215 Self::PlutoLowell => Some("Pluto (Lowell)"),
216 Self::PlutoPickering => Some("Pluto (Pickering)"),
217 Self::Vulcan => Some("Vulcan"),
218 Self::WhiteMoon => Some("White Moon"),
219 Self::Proserpina => Some("Proserpina"),
220 Self::Waldemath => Some("Waldemath"),
221 Self::Custom(_) => None,
222 }
223 }
224
225 pub fn validate(&self) -> Result<(), CustomDefinitionValidationError> {
231 match self {
232 Self::Custom(custom) => custom.validate(),
233 _ => Ok(()),
234 }
235 }
236}
237
238impl fmt::Display for CelestialBody {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 match self {
241 Self::Sun => f.write_str("Sun"),
242 Self::Moon => f.write_str("Moon"),
243 Self::Mercury => f.write_str("Mercury"),
244 Self::Venus => f.write_str("Venus"),
245 Self::Mars => f.write_str("Mars"),
246 Self::Jupiter => f.write_str("Jupiter"),
247 Self::Saturn => f.write_str("Saturn"),
248 Self::Uranus => f.write_str("Uranus"),
249 Self::Neptune => f.write_str("Neptune"),
250 Self::Pluto => f.write_str("Pluto"),
251 Self::MeanNode => f.write_str("Mean Node"),
252 Self::TrueNode => f.write_str("True Node"),
253 Self::MeanApogee => f.write_str("Mean Apogee"),
254 Self::TrueApogee => f.write_str("True Apogee"),
255 Self::MeanPerigee => f.write_str("Mean Perigee"),
256 Self::TruePerigee => f.write_str("True Perigee"),
257 Self::Ceres => f.write_str("Ceres"),
258 Self::Pallas => f.write_str("Pallas"),
259 Self::Juno => f.write_str("Juno"),
260 Self::Vesta => f.write_str("Vesta"),
261 Self::Cupido => f.write_str("Cupido"),
262 Self::Hades => f.write_str("Hades"),
263 Self::Zeus => f.write_str("Zeus"),
264 Self::Kronos => f.write_str("Kronos"),
265 Self::Apollon => f.write_str("Apollon"),
266 Self::Admetos => f.write_str("Admetos"),
267 Self::Vulkanus => f.write_str("Vulkanus"),
268 Self::Poseidon => f.write_str("Poseidon"),
269 Self::Transpluto => f.write_str("Transpluto"),
270 Self::Nibiru => f.write_str("Nibiru"),
271 Self::Harrington => f.write_str("Harrington"),
272 Self::NeptuneLeverrier => f.write_str("Neptune (Leverrier)"),
273 Self::NeptuneAdams => f.write_str("Neptune (Adams)"),
274 Self::PlutoLowell => f.write_str("Pluto (Lowell)"),
275 Self::PlutoPickering => f.write_str("Pluto (Pickering)"),
276 Self::Vulcan => f.write_str("Vulcan"),
277 Self::WhiteMoon => f.write_str("White Moon"),
278 Self::Proserpina => f.write_str("Proserpina"),
279 Self::Waldemath => f.write_str("Waldemath"),
280 Self::Custom(custom) => fmt::Display::fmt(custom, f),
281 }
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 #[test]
290 fn fictitious_bodies_map_to_fictitious_class() {
291 for body in [
292 CelestialBody::Cupido,
293 CelestialBody::Transpluto,
294 CelestialBody::Vulcan,
295 CelestialBody::WhiteMoon,
296 CelestialBody::Waldemath,
297 ] {
298 assert_eq!(body.class(), CelestialBodyClass::Fictitious);
299 assert!(body.built_in_name().is_some());
300 assert!(!body.to_string().is_empty());
301 }
302 assert_eq!(
303 CelestialBody::Transpluto.built_in_name(),
304 Some("Transpluto")
305 );
306 assert_eq!(CelestialBody::WhiteMoon.to_string(), "White Moon");
307 }
308}