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}