use core::fmt;
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum PrincipiaError {
DegenerateGeometry {
reason: &'static str,
},
InvalidStepRequest {
reason: &'static str,
},
InvalidTolerance {
context: &'static str,
},
InvalidParameter {
reason: &'static str,
},
NonPositiveValue {
context: &'static str,
},
NonFiniteValue {
context: &'static str,
},
InvalidGravityRequest {
reason: &'static str,
},
InvalidPropagationConfig {
reason: &'static str,
},
StepControlFailed {
reason: &'static str,
},
StepBelowMinimum {
reason: &'static str,
},
GravityCoefficientUnavailable {
degree: u16,
order: u16,
},
GeopotentialDegreeOutOfRange {
requested: usize,
max: usize,
},
PartialsUnavailable {
model: &'static str,
},
PropagationFailed {
reason: &'static str,
},
ContextDataUnavailable {
what: &'static str,
},
}
impl fmt::Display for PrincipiaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::DegenerateGeometry { reason } => {
write!(f, "degenerate geometry: {reason}")
}
Self::InvalidStepRequest { reason } => {
write!(f, "invalid step request: {reason}")
}
Self::InvalidTolerance { context } => {
write!(f, "invalid tolerance: {context}")
}
Self::InvalidParameter { reason } => {
write!(f, "invalid parameter: {reason}")
}
Self::NonPositiveValue { context } => {
write!(f, "non-positive value: {context}")
}
Self::NonFiniteValue { context } => {
write!(f, "non-finite value: {context}")
}
Self::InvalidGravityRequest { reason } => {
write!(f, "invalid gravity request: {reason}")
}
Self::InvalidPropagationConfig { reason } => {
write!(f, "invalid propagation config: {reason}")
}
Self::StepControlFailed { reason } => {
write!(f, "step controller failed: {reason}")
}
Self::StepBelowMinimum { reason } => {
write!(f, "step below minimum: {reason}")
}
Self::GravityCoefficientUnavailable { degree, order } => {
write!(
f,
"gravity coefficient C_{degree},{order} not available in current model"
)
}
Self::GeopotentialDegreeOutOfRange { requested, max } => {
write!(
f,
"requested geopotential degree {requested} exceeds provider maximum {max}"
)
}
Self::PartialsUnavailable { model } => {
write!(f, "analytic partials not available for model '{model}'")
}
Self::PropagationFailed { reason } => {
write!(f, "propagation failed: {reason}")
}
Self::ContextDataUnavailable { what } => {
write!(f, "context data unavailable: {what}")
}
}
}
}
impl core::error::Error for PrincipiaError {}
#[cfg(test)]
mod tests {
use alloc::string::ToString;
#[cfg(any(feature = "alloc", feature = "std"))]
#[test]
fn display_examples() {
use super::PrincipiaError;
assert!(PrincipiaError::DegenerateGeometry { reason: "r=0" }
.to_string()
.contains("r=0"));
assert!(PrincipiaError::InvalidStepRequest { reason: "h<=0" }
.to_string()
.contains("h<=0"));
assert!(PrincipiaError::GravityCoefficientUnavailable {
degree: 8,
order: 3
}
.to_string()
.contains("C_8,3"));
assert!(PrincipiaError::GeopotentialDegreeOutOfRange {
requested: 70,
max: 21
}
.to_string()
.contains("70"));
assert!(PrincipiaError::PartialsUnavailable { model: "drag" }
.to_string()
.contains("drag"));
assert!(PrincipiaError::PropagationFailed { reason: "NaN" }
.to_string()
.contains("NaN"));
assert!(PrincipiaError::ContextDataUnavailable { what: "ephemeris" }
.to_string()
.contains("ephemeris"));
}
#[test]
fn display_all_new_variants() {
use super::PrincipiaError;
let s = PrincipiaError::InvalidTolerance { context: "rtol" }.to_string();
assert!(s.contains("rtol"), "got: {s}");
let s = PrincipiaError::InvalidParameter {
reason: "h_min>h_max",
}
.to_string();
assert!(s.contains("h_min>h_max"), "got: {s}");
let s = PrincipiaError::NonPositiveValue { context: "mu" }.to_string();
assert!(s.contains("mu"), "got: {s}");
let s = PrincipiaError::NonFiniteValue {
context: "position",
}
.to_string();
assert!(s.contains("position"), "got: {s}");
let s = PrincipiaError::InvalidGravityRequest {
reason: "degree too high",
}
.to_string();
assert!(s.contains("degree"), "got: {s}");
let s = PrincipiaError::InvalidPropagationConfig {
reason: "h0 is zero",
}
.to_string();
assert!(s.contains("h0"), "got: {s}");
let s = PrincipiaError::StepControlFailed { reason: "diverged" }.to_string();
assert!(s.contains("diverged"), "got: {s}");
let s = PrincipiaError::StepBelowMinimum {
reason: "too small",
}
.to_string();
assert!(s.contains("too small"), "got: {s}");
}
#[test]
fn error_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<super::PrincipiaError>();
}
}