openapi_nexus_config/
config_file.rs

1//! Configuration file structure for TOML deserialization
2
3use std::collections::HashMap;
4use std::fmt;
5use std::str::FromStr;
6
7use serde::Deserialize;
8
9use crate::global_config::GlobalConfig;
10use openapi_nexus_common::GeneratorType;
11
12/// Configuration file structure (for deserialization from TOML)
13#[derive(Debug, Clone, Default)]
14pub struct ConfigFile {
15    /// Global settings
16    pub global: GlobalConfig,
17    /// Generator-specific configurations stored as TOML tables
18    pub generators: HashMap<GeneratorType, toml::value::Table>,
19}
20
21impl<'de> Deserialize<'de> for ConfigFile {
22    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
23    where
24        D: serde::Deserializer<'de>,
25    {
26        use serde::de::{Error, MapAccess, Visitor};
27
28        struct ConfigFileVisitor;
29
30        impl<'de> Visitor<'de> for ConfigFileVisitor {
31            type Value = ConfigFile;
32
33            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
34                formatter.write_str("a TOML table")
35            }
36
37            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
38            where
39                A: MapAccess<'de>,
40            {
41                let mut global = None;
42                let mut generators = HashMap::new();
43
44                while let Some(key) = map.next_key::<String>()? {
45                    if key == "global" {
46                        if global.is_some() {
47                            return Err(A::Error::duplicate_field("global"));
48                        }
49                        global = Some(map.next_value()?);
50                    } else {
51                        // All other keys are treated as generator configs
52                        // Parse the string key as a Generator
53                        let generator = GeneratorType::from_str(&key).map_err(|e| {
54                            A::Error::custom(format!("Invalid generator name '{}': {}", key, e))
55                        })?;
56                        let table = map.next_value::<toml::value::Table>()?;
57                        generators.insert(generator, table);
58                    }
59                }
60
61                Ok(ConfigFile {
62                    global: global.unwrap_or_default(),
63                    generators,
64                })
65            }
66        }
67
68        deserializer.deserialize_map(ConfigFileVisitor)
69    }
70}