use hifitime::Epoch;
use snafu::prelude::*;
use crate::ephemerides::EphemerisError;
use crate::orientations::OrientationError;
use crate::prelude::FrameUid;
use crate::structure::dataset::DataSetError;
use crate::structure::semver::Semver;
use crate::NaifId;
use core::convert::From;
use der::Error as DerError;
use std::io::ErrorKind as IOErrorKind;
#[cfg(feature = "metaload")]
use crate::almanac::metaload::MetaAlmanacError;
#[cfg(feature = "metaload")]
use crate::almanac::metaload::MetaFile;
#[derive(Debug, PartialEq, Snafu)]
#[snafu(visibility(pub))]
pub enum AlmanacError {
#[snafu(display("{action} encountered an error with ephemeris computation {source}"))]
Ephemeris {
action: &'static str,
#[snafu(source(from(EphemerisError, Box::new)))]
source: Box<EphemerisError>,
},
#[snafu(display("{action} encountered an error with orientation computation {source}"))]
Orientation {
action: &'static str,
#[snafu(source(from(OrientationError, Box::new)))]
source: Box<OrientationError>,
},
#[snafu(display("{action} encountered an error {source}"))]
AlmanacPhysics {
action: &'static str,
#[snafu(source(from(PhysicsError, Box::new)))]
source: Box<PhysicsError>,
},
#[snafu(display("{source} encountered when loading {path}"))]
Loading {
path: String,
source: InputOutputError,
},
#[snafu(display("{source} encountered when {action}"))]
TLDataSet {
action: &'static str,
source: DataSetError,
},
#[snafu(display("{err}"))]
GenericError { err: String },
#[cfg(feature = "metaload")]
#[snafu(display("processing file #{fno} ({file:?}) caused an error: {source}"))]
Meta {
fno: usize,
file: MetaFile,
source: MetaAlmanacError,
},
}
pub type AlmanacResult<T> = Result<T, AlmanacError>;
#[derive(Debug, PartialEq, Snafu)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum InputOutputError {
IOError { kind: IOErrorKind },
IOUnknownError,
}
#[derive(Copy, Clone, Debug, Snafu, PartialEq)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum DecodingError {
#[snafu(display(
"could not decode {dataset} data -- need at least {need} doubles but found {got}"
))]
TooFewDoubles {
dataset: &'static str,
got: usize,
need: usize,
},
#[snafu(display("bytes between indexes {start} and {end} could not be read, array contains {size} bytes (data malformed?)"))]
InaccessibleBytes {
start: usize,
end: usize,
size: usize,
},
#[snafu(display("integrity error during decoding: {source}"))]
Integrity {
#[snafu(backtrace)]
source: IntegrityError,
},
#[snafu(display("decoding DER failed: {err}"))]
DecodingDer { err: DerError },
#[snafu(display("somehow casting the data failed"))]
Casting,
#[snafu(display("could not load ANISE data version {got}, expected {exp}"))]
AniseVersion { got: Semver, exp: Semver },
#[snafu(display("data could not be parsed as {kind} despite ANISE version matching (should be loaded as another type?)"))]
Obscure { kind: &'static str },
}
#[derive(Copy, Clone, PartialEq, Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum IntegrityError {
ChecksumInvalid {
expected: Option<u32>,
computed: u32,
},
DataMismatchOnMerge,
DataMissing,
LookupTable,
DisjointRoots {
from_frame: FrameUid,
to_frame: FrameUid,
},
#[snafu(display(
"data for {variable} in {dataset} decoded as subnormal double (data malformed?)"
))]
SubNormal {
dataset: &'static str,
variable: &'static str,
},
#[snafu(display("data for {variable}={value} in {dataset} is invalid {reason}"))]
InvalidValue {
dataset: &'static str,
variable: &'static str,
value: f64,
reason: &'static str,
},
}
#[derive(Copy, Clone, PartialEq, Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum MathError {
#[snafu(display("prevented a division by zero when {action}"))]
DivisionByZero { action: &'static str },
#[snafu(display("{msg}: {value}"))]
DomainError { value: f64, msg: &'static str },
#[snafu(display("max iterations reached ({iter}) when {action}"))]
MaxIterationsReached { iter: usize, action: &'static str },
}
#[derive(Copy, Clone, Debug, Snafu, PartialEq)]
#[snafu(visibility(pub(crate)))]
#[non_exhaustive]
pub enum PhysicsError {
Unreachable,
#[snafu(display("epochs {epoch1} and {epoch2} differ while {action}"))]
EpochMismatch {
action: &'static str,
epoch1: Epoch,
epoch2: Epoch,
},
#[snafu(display("frames {frame1} and {frame2} differ while {action}"))]
FrameMismatch {
action: &'static str,
frame1: FrameUid,
frame2: FrameUid,
},
#[snafu(display(
"cannot {action} because rotations {from1}->{to1} and {from2}->{to2} are incompatible"
))]
InvalidRotation {
action: &'static str,
from1: NaifId,
to1: NaifId,
from2: NaifId,
to2: NaifId,
},
#[snafu(display("cannot rotate state in frame {state_frame} with rotation {from}->{to}"))]
InvalidStateRotation {
from: NaifId,
to: NaifId,
state_frame: FrameUid,
},
#[snafu(display("{action} requires the time derivative of the DCM but it is not set"))]
DCMMissingDerivative { action: &'static str },
#[snafu(display("{action} requires the frame {frame} to have {data} defined"))]
MissingFrameData {
action: &'static str,
data: &'static str,
frame: FrameUid,
},
#[snafu(display("parabolic orbits are physically impossible and the eccentricity calculated to be within {limit:e} of 1.0"))]
ParabolicEccentricity { limit: f64 },
#[snafu(display("parabolic orbits are physically impossible and the semilatus rectum (semi-parameter) calculated to be {p_km} km"))]
ParabolicSemiParam { p_km: f64 },
#[snafu(display("hyperbolic true anomaly is physically impossible: {ta_deg} deg"))]
HyperbolicTrueAnomaly { ta_deg: f64 },
#[snafu(display("calculation requires hyperbolic orbit, but its eccentricity is {ecc}"))]
NotHyperbolic { ecc: f64 },
#[snafu(display("calculation requires non-hyperbolic orbit, but its eccentricity is {ecc}"))]
Hyperbolic { ecc: f64 },
#[snafu(display("mean element computation failed: {detail}"))]
MeanElement { detail: &'static str },
#[snafu(display("infinite value encountered when {action}"))]
InfiniteValue { action: &'static str },
#[snafu(display("{source}"))]
AppliedMath { source: MathError },
#[snafu(display("invalid radius: {action}"))]
RadiusError { action: &'static str },
#[snafu(display("invalid velocity: {action}"))]
VelocityError { action: &'static str },
#[snafu(display("invalid aberration: {action}"))]
AberrationError { action: &'static str },
#[snafu(display("cannot {action} when the record does not define a covariance"))]
NoCovariance { action: &'static str },
#[snafu(display("partials are not yet defined for this orbital element"))]
PartialsNotYetDefined,
}
impl From<IOErrorKind> for InputOutputError {
fn from(kind: IOErrorKind) -> Self {
Self::IOError { kind }
}
}