#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::GetSetString;
use std::os::raw::c_char;
unsafe extern "C" {
pub fn EnvGetInfo(infoStr: *const c_char);
pub fn EnvLoadFile(envFile: *const c_char) -> i32;
pub fn EnvSaveFile(envConstFile: *const c_char, saveMode: i32, saveForm: i32) -> i32;
pub fn EnvGetFkIdx() -> i32;
pub fn EnvSetFkIdx(xf_FkMod: i32);
pub fn EnvGetGeoIdx() -> i32;
pub fn EnvSetGeoIdx(xf_GeoMod: i32);
pub fn EnvGetGeoStr(geoStr: *const c_char);
pub fn EnvSetGeoStr(geoStr: *const c_char);
pub fn EnvGetGeoConst(xf_GeoCon: i32) -> f64;
pub fn EnvGetFkConst(xf_FkCon: i32) -> f64;
pub fn EnvGetFkPtr() -> i64;
pub fn EnvSetEarthShape(earthShape: i32);
pub fn EnvGetEarthShape() -> i32;
}
pub static XF_GEOCON_FF: i32 = 1;
pub static XF_GEOCON_J2: i32 = 2;
pub static XF_GEOCON_J3: i32 = 3;
pub static XF_GEOCON_J4: i32 = 4;
pub static XF_GEOCON_KE: i32 = 5;
pub static XF_GEOCON_KMPER: i32 = 6;
pub static XF_GEOCON_RPTIM: i32 = 7;
pub static XF_GEOCON_CK2: i32 = 8;
pub static XF_GEOCON_CK4: i32 = 9;
pub static XF_GEOCON_KS2EK: i32 = 10;
pub static XF_GEOCON_THDOT: i32 = 11;
pub static XF_GEOCON_J5: i32 = 12;
pub static XF_GEOCON_MU: i32 = 13;
pub static XF_FKCON_C1: i32 = 1;
pub static XF_FKCON_C1DOT: i32 = 2;
pub static XF_FKCON_THGR70: i32 = 3;
pub const XF_GEOMOD_JGM2: i32 = 2;
pub const XF_GEOMOD_GEM5: i32 = 5;
pub const XF_GEOMOD_EGM08: i32 = 8;
pub const XF_GEOMOD_GEM9: i32 = 9;
pub const XF_GEOMOD_STEM68: i32 = 68;
pub const XF_GEOMOD_WGS72: i32 = 72;
pub const XF_GEOMOD_WGS84: i32 = 84;
pub const XF_GEOMOD_EGM96: i32 = 96;
pub const XF_GEOMOD_UNKNOWN: i32 = 100;
pub const XF_FKMOD_4: i32 = 4;
pub const XF_FKMOD_5: i32 = 5;
pub fn get_dll_info() -> String {
let mut info_str = GetSetString::new();
unsafe {
EnvGetInfo(info_str.pointer());
}
info_str.value()
}
pub fn get_earth_radius() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_KMPER) }
}
pub fn get_earth_rotation_rate() -> f64 {
unsafe { EnvGetFkConst(XF_FKCON_C1) }
}
pub fn get_earth_rotation_acceleration() -> f64 {
unsafe { EnvGetFkConst(XF_FKCON_C1DOT) }
}
pub fn get_earth_mu() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_MU) }
}
pub fn get_earth_flattening() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_FF) }
}
pub fn get_j2() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_J2) }
}
pub fn get_j3() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_J3) }
}
pub fn get_j4() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_J4) }
}
pub fn get_j5() -> f64 {
unsafe { EnvGetGeoConst(XF_GEOCON_J5) }
}
pub fn load_from_file(file_path: &str) -> Result<(), String> {
let mut env_file: GetSetString = file_path.into();
let result = unsafe { EnvLoadFile(env_file.pointer()) };
match result {
0 => Ok(()),
_ => Err(format!("Failed to load environment from file: {}", file_path)),
}
}
pub fn get_fundamental_catalog() -> Result<i32, String> {
let fk_idx = unsafe { EnvGetFkIdx() };
match fk_idx {
XF_FKMOD_4 => Ok(fk_idx),
XF_FKMOD_5 => Ok(fk_idx),
_ => Err(format!("Unknown fundamental catalog index: {}", fk_idx)),
}
}
pub fn set_fundamental_catalog(catalog: i32) {
unsafe {
EnvSetFkIdx(catalog);
}
}
pub fn set_geopotential_model(geo_model: i32) {
unsafe {
EnvSetGeoIdx(geo_model);
}
}
pub fn get_geopotential_model() -> Result<i32, String> {
let geo_idx = unsafe { EnvGetGeoIdx() };
match geo_idx {
XF_GEOMOD_UNKNOWN => Err("Unknown geopotential model".to_string()),
_ => Ok(geo_idx),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::DLL_VERSION;
use crate::test_lock::TEST_LOCK;
#[test]
fn test_get_dll_info() {
let _lock = TEST_LOCK.lock().unwrap();
let info = get_dll_info();
assert!(info.contains(DLL_VERSION));
}
#[test]
fn test_get_earth_radius() {
let _lock = TEST_LOCK.lock().unwrap();
let radius = get_earth_radius();
assert!(radius == 6378.135);
}
#[test]
fn test_get_fundamental_catalog() {
let _lock = TEST_LOCK.lock().unwrap();
let catalog = get_fundamental_catalog().unwrap();
assert!(catalog == 5);
}
#[test]
fn test_get_j2() {
let _lock = TEST_LOCK.lock().unwrap();
let j2 = get_j2();
assert_eq!(j2, 0.001082616);
}
#[test]
fn test_get_j3() {
let _lock = TEST_LOCK.lock().unwrap();
let j3 = get_j3();
assert_eq!(j3, -0.00000253881);
}
#[test]
fn test_get_j4() {
let _lock = TEST_LOCK.lock().unwrap();
let j4 = get_j4();
assert_eq!(j4, -0.00000165597);
}
#[test]
fn test_get_j5() {
let _lock = TEST_LOCK.lock().unwrap();
let j5 = get_j5();
assert_eq!(j5, -2.184827e-7);
}
#[test]
fn test_get_earth_mu() {
let _lock = TEST_LOCK.lock().unwrap();
let mu = get_earth_mu();
assert_eq!(mu, 398600.8);
}
#[test]
fn test_get_earth_flattening() {
let _lock = TEST_LOCK.lock().unwrap();
let ff = get_earth_flattening();
assert_eq!(ff, 1.0 / 298.26);
}
#[test]
fn test_get_earth_rotation_rate() {
let _lock = TEST_LOCK.lock().unwrap();
let rate = get_earth_rotation_rate();
assert_eq!(rate, 0.017202791694070362);
}
#[test]
fn test_get_earth_rotation_acceleration() {
let _lock = TEST_LOCK.lock().unwrap();
let accel = get_earth_rotation_acceleration();
assert_eq!(accel, 5.075514194322695e-15);
}
#[test]
fn test_set_fundamental_catalog_four() {
let _lock = TEST_LOCK.lock().unwrap();
set_fundamental_catalog(4);
let catalog = get_fundamental_catalog().unwrap();
assert_eq!(catalog, 4);
set_fundamental_catalog(5);
}
#[test]
fn test_load_from_file_missing() {
let _lock = TEST_LOCK.lock().unwrap();
let path = std::env::temp_dir().join("saal_missing_env.txt");
let _ = std::fs::remove_file(&path);
let result = load_from_file(path.to_str().unwrap());
assert!(result.is_err());
}
}