anise/naif/kpl/
mod.rs

1/*
2 * ANISE Toolkit
3 * Copyright (C) 2021-onward Christopher Rabotin <christopher.rabotin@gmail.com> et al. (cf. AUTHORS.md)
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * Documentation: https://nyxspace.com/
9 */
10
11use core::str::FromStr;
12use std::fmt::Debug;
13use std::{collections::HashMap, hash::Hash};
14
15use snafu::{whatever, Whatever};
16
17use self::parser::Assignment;
18
19pub mod fk;
20
21pub mod parser;
22pub mod tpc;
23
24pub trait KPLItem: Debug + Default {
25    type Parameter: Eq + Hash;
26    /// The key used for fetching
27    fn extract_key(data: &Assignment) -> i32;
28    fn data(&self) -> &HashMap<Self::Parameter, KPLValue>;
29    fn parse(&mut self, data: Assignment);
30}
31
32#[derive(Clone, Debug, PartialEq)]
33pub enum KPLValue {
34    Float(f64),
35    Matrix(Vec<f64>),
36    String(String),
37    Integer(i32),
38}
39
40impl KPLValue {
41    pub fn to_vec_f64(&self) -> Result<Vec<f64>, Whatever> {
42        match self {
43            KPLValue::Matrix(data) => Ok(data.clone()),
44            _ => whatever!("can only convert matrices to vec of f64 but this is {self:?}"),
45        }
46    }
47
48    pub fn to_i32(&self) -> Result<i32, Whatever> {
49        match self {
50            KPLValue::Integer(data) => Ok(*data),
51            _ => whatever!("can only convert Integer to i32 but this is {self:?}"),
52        }
53    }
54
55    pub fn to_string(&self) -> Result<String, Whatever> {
56        match self {
57            KPLValue::String(data) => Ok(data.clone()),
58            _ => whatever!("can only convert Integer to i32 but this is {self:?}"),
59        }
60    }
61}
62
63impl From<f64> for KPLValue {
64    fn from(value: f64) -> Self {
65        Self::Float(value)
66    }
67}
68
69impl From<i32> for KPLValue {
70    fn from(value: i32) -> Self {
71        Self::Integer(value)
72    }
73}
74
75impl From<String> for KPLValue {
76    fn from(value: String) -> Self {
77        Self::String(value)
78    }
79}
80
81impl TryFrom<&KPLValue> for f64 {
82    type Error = Whatever;
83
84    fn try_from(value: &KPLValue) -> Result<Self, Self::Error> {
85        match value {
86            KPLValue::Float(data) => Ok(*data),
87            _ => whatever!("can only convert float to f64 but this is {value:?}"),
88        }
89    }
90}
91
92/// Known KPL parameters
93#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
94pub enum Parameter {
95    NutPrecRa,
96    NutPrecDec,
97    NutPrecPm,
98    NutPrecAngles,
99    MaxPhaseDegree,
100    LongAxis,
101    PoleRa,
102    PoleDec,
103    Radii,
104    PrimeMeridian,
105    GeoMagNorthPoleCenterDipoleLatitude,
106    GeoMagNorthPoleCenterDipoleLongitude,
107    GravitationalParameter,
108    Class,
109    Center,
110    ClassId,
111    Angles,
112    Relative,
113    Matrix,
114    Units,
115    Axes,
116}
117
118impl FromStr for Parameter {
119    type Err = Whatever;
120
121    fn from_str(s: &str) -> Result<Self, Self::Err> {
122        match s {
123            "NUT_PREC_RA" => Ok(Self::NutPrecRa),
124            "NUT_PREC_DEC" => Ok(Self::NutPrecDec),
125            "NUT_PREC_PM" => Ok(Self::NutPrecPm),
126            "LONG_AXIS" => Ok(Self::LongAxis),
127            "POLE_DEC" => Ok(Self::PoleDec),
128            "POLE_RA" => Ok(Self::PoleRa),
129            "RADII" => Ok(Self::Radii),
130            "PM" => Ok(Self::PrimeMeridian),
131            "NUT_PREC_ANGLES" => Ok(Self::NutPrecAngles),
132            "N_GEOMAG_CTR_DIPOLE_LAT" => Ok(Self::GeoMagNorthPoleCenterDipoleLatitude),
133            "N_GEOMAG_CTR_DIPOLE_LON" => Ok(Self::GeoMagNorthPoleCenterDipoleLongitude),
134            "GM" => Ok(Self::GravitationalParameter),
135            "CLASS" => Ok(Self::Class),
136            "CLASS_ID" => Ok(Self::ClassId),
137            "CENTER" => Ok(Self::Center),
138            "ANGLES" => Ok(Self::Angles),
139            "RELATIVE" => Ok(Self::Relative),
140            "MATRIX" => Ok(Self::Matrix),
141            "UNITS" => Ok(Self::Units),
142            "AXES" => Ok(Self::Axes),
143            "MAX_PHASE_DEGREE" => Ok(Self::MaxPhaseDegree),
144            "GMLIST" | "NAME" | "SPEC" => {
145                whatever!("unsupported parameter `{s}`")
146            }
147            _ => {
148                whatever!("unknown parameter `{s}`")
149            }
150        }
151    }
152}