rust_jpl/
config.rs

1//! Configuration management for ephemeris data
2
3use config::{Config, File};
4use serde::Deserialize;
5use std::fs;
6use std::fs::File as StdFile;
7use std::io::{self, Read};
8
9use crate::Error;
10
11#[derive(Debug, Deserialize)]
12struct ConfigPaths {
13    nasa_jpl_de441: String,
14    header_441: String,
15    initial_data_dat: String,
16}
17
18#[derive(Debug, Deserialize)]
19struct ConfigFile {
20    paths: ConfigPaths,
21}
22
23/// Configuration for the ephemeris system
24#[derive(Debug, Clone)]
25pub struct AppConfig {
26    pub nasa_jpl_de441: String,
27    pub header_441: String,
28    pub initial_data_dat: String,
29}
30
31impl AppConfig {
32    /// Create a new configuration from a config file
33    ///
34    /// # Arguments
35    /// * `config_path` - Path to the config.toml file
36    pub fn new(config_path: &str) -> Result<Self, Error> {
37        let config = Config::builder()
38            .add_source(File::with_name(config_path))
39            .build()
40            .map_err(|e| Error::Config(format!("Failed to load {}: {}", config_path, e)))?;
41
42        let config_file: ConfigFile = config
43            .try_deserialize()
44            .map_err(|e| Error::Config(format!("Failed to deserialize config: {}", e)))?;
45
46        let nasa_jpl_de441 = config_file.paths.nasa_jpl_de441.clone();
47        let header_441 = config_file.paths.header_441.clone();
48        let initial_data_dat = config_file.paths.initial_data_dat.clone();
49
50        Self::validate_file(&nasa_jpl_de441)?;
51        Self::validate_file(&header_441)?;
52        Self::validate_file(&initial_data_dat)?;
53
54        Ok(Self {
55            nasa_jpl_de441,
56            header_441,
57            initial_data_dat,
58        })
59    }
60
61    fn validate_file(file_path: &str) -> Result<(), Error> {
62        fs::metadata(file_path)
63            .map_err(|_| Error::Config(format!("Required file not found: {}", file_path)))?;
64        Ok(())
65    }
66
67    /// Read the NASA JPL DE441 binary file
68    pub fn read_nasa_jpl_de441(&self) -> Result<Vec<u8>, Error> {
69        read_file(&self.nasa_jpl_de441).map_err(Error::from)
70    }
71
72    /// Read the header file
73    pub fn read_header_441(&self) -> Result<Vec<u8>, Error> {
74        read_file(&self.header_441).map_err(Error::from)
75    }
76
77    /// Read the initial data file
78    pub fn read_initial_data_dat(&self) -> Result<Vec<u8>, Error> {
79        read_file(&self.initial_data_dat).map_err(Error::from)
80    }
81}
82
83fn read_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
84    let mut file = StdFile::open(file_path)?;
85    let mut buffer = Vec::new();
86    file.read_to_end(&mut buffer)?;
87    Ok(buffer)
88}