sora-input-toml 0.3.0

Simple and powerful configuration table compiler for games and data-heavy tools.
Documentation
use std::path::{Path, PathBuf};

use sora_data::model::{ConfigData, LocalizationData, LocalizationRowData, LocalizationSourceData};
use sora_diagnostics::Result;
use sora_input::traits::DataInput;
use sora_ir::model::ConfigIr;

use crate::data::{load_config_data, load_table_data_file};

#[derive(Debug, Clone)]
pub struct TomlDataInput {
    data_root: PathBuf,
}

impl TomlDataInput {
    pub fn new(data_root: impl Into<PathBuf>) -> Self {
        Self {
            data_root: data_root.into(),
        }
    }

    pub fn data_root(&self) -> &Path {
        &self.data_root
    }
}

impl DataInput for TomlDataInput {
    fn load_data(&self, ir: &ConfigIr) -> Result<ConfigData> {
        load_config_data(ir, &self.data_root)
    }

    fn load_localization_data(&self, ir: &ConfigIr) -> Result<LocalizationData> {
        let Some(localization) = &ir.localization else {
            return Ok(LocalizationData::default());
        };
        let mut sources = Vec::with_capacity(localization.sources.len());
        for source in &localization.sources {
            let table = load_table_data_file(&source.name, &self.data_root.join(&source.file))?;
            let mut columns = Vec::new();
            let mut rows = Vec::with_capacity(table.rows.len());
            for row in table.rows {
                let mut values = std::collections::BTreeMap::new();
                for (field, value) in row.values {
                    if let sora_data::model::Value::String(value) = value {
                        if !columns.iter().any(|column| column == &field) {
                            columns.push(field.clone());
                        }
                        values.insert(field, value);
                    }
                }
                rows.push(LocalizationRowData { values });
            }
            sources.push(LocalizationSourceData {
                name: source.name.clone(),
                columns,
                rows,
            });
        }
        Ok(LocalizationData { sources })
    }
}