apple_bindgen/
config.rs

1use serde::Deserialize;
2use std::collections::HashMap;
3use thiserror::Error;
4
5#[derive(Deserialize)]
6pub struct ConfigMap {
7    #[serde(flatten)]
8    map: HashMap<String, FileConfig>,
9}
10
11impl ConfigMap {
12    pub fn from_str(content: &str) -> Result<Self, ConfigError> {
13        toml::from_str(&content).map_err(|e| ConfigError::TomlError(e))
14    }
15
16    pub fn from_file(path: impl AsRef<std::path::Path>) -> Result<Self, ConfigError> {
17        let content = std::fs::read_to_string(path).map_err(|e| ConfigError::OpenError(e))?;
18        Self::from_str(&content)
19    }
20
21    pub fn with_builtin_config() -> Self {
22        let content = include_str!("../Bindgen.toml");
23        Self::from_str(content).expect("Builtin config file is corrupted. This is bug.")
24    }
25
26    pub fn framework_config(&self, name: &str) -> Config {
27        let mut deps = Vec::new();
28        if self.map.contains_key(name) {
29            deps.push(name);
30        }
31
32        let mut i = 0;
33        while i < deps.len() {
34            let dep = deps[i];
35            let config = self
36                .map
37                .get(dep)
38                .unwrap_or_else(|| panic!("wrong dependency name {dep}"));
39            for dep in &config.deps {
40                if deps.contains(&dep.as_str()) {
41                    continue;
42                }
43                deps.push(dep.as_str());
44            }
45            i += 1;
46        }
47        deps.push("default");
48        {
49            let mut cloned = deps.clone();
50            cloned.sort_unstable();
51            cloned.dedup();
52            assert_eq!(deps.len(), cloned.len());
53        }
54
55        deps.into_iter()
56            .map(|dep| &self.map.get(dep).unwrap().config)
57            .collect()
58    }
59}
60
61impl<'a> FromIterator<&'a Config> for Config {
62    fn from_iter<T: IntoIterator<Item = &'a Config>>(iter: T) -> Self {
63        let mut opaque_types = Vec::new();
64        let mut blocklist_items = Vec::new();
65        let mut impl_debugs = Vec::new();
66        let mut replacements = Vec::new();
67        let mut layout_tests = false;
68        for config in iter {
69            opaque_types.extend(config.opaque_types.iter().cloned());
70            blocklist_items.extend(config.blocklist_items.iter().cloned());
71            impl_debugs.extend(config.impl_debugs.iter().cloned());
72            replacements.extend(config.replacements.iter().cloned());
73            layout_tests |= config.layout_tests;
74        }
75        Self {
76            opaque_types,
77            blocklist_items,
78            impl_debugs,
79            replacements,
80            layout_tests,
81        }
82    }
83}
84
85#[derive(Deserialize, Default)]
86pub struct FileConfig {
87    #[serde(default)]
88    deps: Vec<String>,
89    #[serde(flatten)]
90    config: Config,
91}
92
93#[derive(Deserialize, Default, Debug, Clone)]
94pub struct Config {
95    #[serde(default)]
96    pub opaque_types: Vec<String>,
97    #[serde(default)]
98    pub blocklist_items: Vec<String>,
99    #[serde(default)]
100    pub impl_debugs: Vec<String>,
101    #[serde(default)]
102    pub replacements: Vec<String>,
103    #[serde(default)]
104    pub layout_tests: bool,
105}
106
107#[non_exhaustive]
108#[derive(Debug, Error)]
109pub enum ConfigError {
110    #[error("toml parsing error {0}")]
111    OpenError(std::io::Error),
112    #[error("toml parsing error {0}")]
113    TomlError(toml::de::Error),
114}