runmat-config 0.6.2

Shared configuration schema and loaders for RunMat
Documentation
use super::{RunmatConfigDocumentError, RunmatConfigFormat};
use crate::desktop::DesktopConfig;
use crate::runtime::{
    AccelerateConfig, FeaConfig, GcConfig, JitConfig, LanguageConfig, LoggingConfig,
    PlottingConfig, RunMatRuntimeConfig, TelemetryConfig,
};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

#[derive(Debug, Deserialize, Default)]
pub(super) struct ConfigProjection {
    #[serde(default)]
    pub desktop: DesktopConfig,
    #[serde(default)]
    runtime: RuntimeSection,
    #[serde(flatten)]
    _other: BTreeMap<String, serde::de::IgnoredAny>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(default, deny_unknown_fields)]
pub(super) struct RuntimeSection {
    callstack_limit: Option<usize>,
    error_namespace: Option<String>,
    verbose: Option<bool>,
    language: Option<LanguageConfig>,
    logging: Option<LoggingConfig>,
    telemetry: Option<TelemetryConfig>,
    jit: Option<JitConfig>,
    gc: Option<GcConfig>,
    accelerate: Option<AccelerateConfig>,
    plotting: Option<PlottingConfig>,
    fea: Option<FeaConfig>,
}

impl From<&RunMatRuntimeConfig> for RuntimeSection {
    fn from(value: &RunMatRuntimeConfig) -> Self {
        Self {
            callstack_limit: Some(value.runtime.callstack_limit),
            error_namespace: Some(value.runtime.error_namespace.clone()),
            verbose: Some(value.runtime.verbose),
            language: Some(value.language.clone()),
            logging: Some(value.logging.clone()),
            telemetry: Some(value.telemetry.clone()),
            jit: Some(value.jit.clone()),
            gc: Some(value.gc.clone()),
            accelerate: Some(value.accelerate.clone()),
            plotting: Some(value.plotting.clone()),
            fea: Some(value.fea.clone()),
        }
    }
}

impl RuntimeSection {
    fn resolve(self) -> RunMatRuntimeConfig {
        let mut config = RunMatRuntimeConfig::default();
        if let Some(value) = self.callstack_limit {
            config.runtime.callstack_limit = value;
        }
        if let Some(value) = self.error_namespace {
            config.runtime.error_namespace = value;
        }
        if let Some(value) = self.verbose {
            config.runtime.verbose = value;
        }
        if let Some(value) = self.language {
            config.language = value;
        }
        if let Some(value) = self.logging {
            config.logging = value;
        }
        if let Some(value) = self.telemetry {
            config.telemetry = value;
        }
        if let Some(value) = self.jit {
            config.jit = value;
        }
        if let Some(value) = self.gc {
            config.gc = value;
        }
        if let Some(value) = self.accelerate {
            config.accelerate = value;
        }
        if let Some(value) = self.plotting {
            config.plotting = value;
        }
        if let Some(value) = self.fea {
            config.fea = value;
        }
        config
    }
}

pub(super) struct ResolvedProjection {
    pub desktop: DesktopConfig,
    pub runtime: RunMatRuntimeConfig,
}

pub(super) fn parse_projection(
    source: &str,
    format: RunmatConfigFormat,
) -> Result<ResolvedProjection, RunmatConfigDocumentError> {
    let projection: ConfigProjection = match format {
        RunmatConfigFormat::Toml => toml_edit::de::from_str(source)
            .map_err(|error| RunmatConfigDocumentError::TomlParse(error.to_string()))?,
        RunmatConfigFormat::Json => serde_json::from_str(source)?,
    };
    Ok(ResolvedProjection {
        desktop: projection.desktop,
        runtime: projection.runtime.resolve(),
    })
}