use core::fmt;
use crate::custom_bodies::{CustomBodyId, CustomDefinitionValidationError};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
#[non_exhaustive]
pub enum CelestialBodyClass {
Luminary,
MajorPlanet,
LunarPoint,
BuiltInAsteroid,
Fictitious,
Custom,
}
impl CelestialBodyClass {
pub const fn label(self) -> &'static str {
match self {
Self::Luminary => "luminary",
Self::MajorPlanet => "major planet",
Self::LunarPoint => "lunar point",
Self::BuiltInAsteroid => "built-in asteroid",
Self::Fictitious => "fictitious body",
Self::Custom => "custom body",
}
}
}
impl fmt::Display for CelestialBodyClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.label())
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum CelestialBody {
Sun,
Moon,
Mercury,
Venus,
Mars,
Jupiter,
Saturn,
Uranus,
Neptune,
Pluto,
MeanNode,
TrueNode,
MeanApogee,
TrueApogee,
MeanPerigee,
TruePerigee,
Ceres,
Pallas,
Juno,
Vesta,
Cupido,
Hades,
Zeus,
Kronos,
Apollon,
Admetos,
Vulkanus,
Poseidon,
Transpluto,
Nibiru,
Harrington,
NeptuneLeverrier,
NeptuneAdams,
PlutoLowell,
PlutoPickering,
Vulcan,
WhiteMoon,
Proserpina,
Waldemath,
Custom(CustomBodyId),
}
impl CelestialBody {
pub const fn class(&self) -> CelestialBodyClass {
match self {
Self::Sun | Self::Moon => CelestialBodyClass::Luminary,
Self::Mercury
| Self::Venus
| Self::Mars
| Self::Jupiter
| Self::Saturn
| Self::Uranus
| Self::Neptune
| Self::Pluto => CelestialBodyClass::MajorPlanet,
Self::MeanNode
| Self::TrueNode
| Self::MeanApogee
| Self::TrueApogee
| Self::MeanPerigee
| Self::TruePerigee => CelestialBodyClass::LunarPoint,
Self::Ceres | Self::Pallas | Self::Juno | Self::Vesta => {
CelestialBodyClass::BuiltInAsteroid
}
Self::Cupido
| Self::Hades
| Self::Zeus
| Self::Kronos
| Self::Apollon
| Self::Admetos
| Self::Vulkanus
| Self::Poseidon
| Self::Transpluto
| Self::Nibiru
| Self::Harrington
| Self::NeptuneLeverrier
| Self::NeptuneAdams
| Self::PlutoLowell
| Self::PlutoPickering
| Self::Vulcan
| Self::WhiteMoon
| Self::Proserpina
| Self::Waldemath => CelestialBodyClass::Fictitious,
Self::Custom(_) => CelestialBodyClass::Custom,
}
}
pub const fn built_in_name(&self) -> Option<&'static str> {
match self {
Self::Sun => Some("Sun"),
Self::Moon => Some("Moon"),
Self::Mercury => Some("Mercury"),
Self::Venus => Some("Venus"),
Self::Mars => Some("Mars"),
Self::Jupiter => Some("Jupiter"),
Self::Saturn => Some("Saturn"),
Self::Uranus => Some("Uranus"),
Self::Neptune => Some("Neptune"),
Self::Pluto => Some("Pluto"),
Self::MeanNode => Some("Mean Node"),
Self::TrueNode => Some("True Node"),
Self::MeanApogee => Some("Mean Apogee"),
Self::TrueApogee => Some("True Apogee"),
Self::MeanPerigee => Some("Mean Perigee"),
Self::TruePerigee => Some("True Perigee"),
Self::Ceres => Some("Ceres"),
Self::Pallas => Some("Pallas"),
Self::Juno => Some("Juno"),
Self::Vesta => Some("Vesta"),
Self::Cupido => Some("Cupido"),
Self::Hades => Some("Hades"),
Self::Zeus => Some("Zeus"),
Self::Kronos => Some("Kronos"),
Self::Apollon => Some("Apollon"),
Self::Admetos => Some("Admetos"),
Self::Vulkanus => Some("Vulkanus"),
Self::Poseidon => Some("Poseidon"),
Self::Transpluto => Some("Transpluto"),
Self::Nibiru => Some("Nibiru"),
Self::Harrington => Some("Harrington"),
Self::NeptuneLeverrier => Some("Neptune (Leverrier)"),
Self::NeptuneAdams => Some("Neptune (Adams)"),
Self::PlutoLowell => Some("Pluto (Lowell)"),
Self::PlutoPickering => Some("Pluto (Pickering)"),
Self::Vulcan => Some("Vulcan"),
Self::WhiteMoon => Some("White Moon"),
Self::Proserpina => Some("Proserpina"),
Self::Waldemath => Some("Waldemath"),
Self::Custom(_) => None,
}
}
pub fn validate(&self) -> Result<(), CustomDefinitionValidationError> {
match self {
Self::Custom(custom) => custom.validate(),
_ => Ok(()),
}
}
}
impl fmt::Display for CelestialBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Sun => f.write_str("Sun"),
Self::Moon => f.write_str("Moon"),
Self::Mercury => f.write_str("Mercury"),
Self::Venus => f.write_str("Venus"),
Self::Mars => f.write_str("Mars"),
Self::Jupiter => f.write_str("Jupiter"),
Self::Saturn => f.write_str("Saturn"),
Self::Uranus => f.write_str("Uranus"),
Self::Neptune => f.write_str("Neptune"),
Self::Pluto => f.write_str("Pluto"),
Self::MeanNode => f.write_str("Mean Node"),
Self::TrueNode => f.write_str("True Node"),
Self::MeanApogee => f.write_str("Mean Apogee"),
Self::TrueApogee => f.write_str("True Apogee"),
Self::MeanPerigee => f.write_str("Mean Perigee"),
Self::TruePerigee => f.write_str("True Perigee"),
Self::Ceres => f.write_str("Ceres"),
Self::Pallas => f.write_str("Pallas"),
Self::Juno => f.write_str("Juno"),
Self::Vesta => f.write_str("Vesta"),
Self::Cupido => f.write_str("Cupido"),
Self::Hades => f.write_str("Hades"),
Self::Zeus => f.write_str("Zeus"),
Self::Kronos => f.write_str("Kronos"),
Self::Apollon => f.write_str("Apollon"),
Self::Admetos => f.write_str("Admetos"),
Self::Vulkanus => f.write_str("Vulkanus"),
Self::Poseidon => f.write_str("Poseidon"),
Self::Transpluto => f.write_str("Transpluto"),
Self::Nibiru => f.write_str("Nibiru"),
Self::Harrington => f.write_str("Harrington"),
Self::NeptuneLeverrier => f.write_str("Neptune (Leverrier)"),
Self::NeptuneAdams => f.write_str("Neptune (Adams)"),
Self::PlutoLowell => f.write_str("Pluto (Lowell)"),
Self::PlutoPickering => f.write_str("Pluto (Pickering)"),
Self::Vulcan => f.write_str("Vulcan"),
Self::WhiteMoon => f.write_str("White Moon"),
Self::Proserpina => f.write_str("Proserpina"),
Self::Waldemath => f.write_str("Waldemath"),
Self::Custom(custom) => fmt::Display::fmt(custom, f),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fictitious_bodies_map_to_fictitious_class() {
for body in [
CelestialBody::Cupido,
CelestialBody::Transpluto,
CelestialBody::Vulcan,
CelestialBody::WhiteMoon,
CelestialBody::Waldemath,
] {
assert_eq!(body.class(), CelestialBodyClass::Fictitious);
assert!(body.built_in_name().is_some());
assert!(!body.to_string().is_empty());
}
assert_eq!(
CelestialBody::Transpluto.built_in_name(),
Some("Transpluto")
);
assert_eq!(CelestialBody::WhiteMoon.to_string(), "White Moon");
}
}