rusteal_codegen/
config.rs1use serde::Deserialize;
9use std::collections::HashMap;
10use std::path::{Path, PathBuf};
11
12pub const FILE_NAME: &str = "rusteal.toml";
14
15#[derive(Deserialize)]
17pub struct ProjectConfig {
18 pub project: ProjectSection,
19 pub codegen: CodegenConfig,
20}
21
22#[derive(Deserialize)]
23pub struct ProjectSection {
24 #[serde(rename = "crate")]
26 pub crate_name: String,
27 #[serde(default)]
29 pub features: Vec<String>,
30}
31
32#[derive(Deserialize)]
33pub struct CodegenConfig {
34 pub features: Vec<String>,
35 pub modules: HashMap<String, ModuleMapping>,
36 #[serde(default)]
37 pub blocklist: Blocklist,
38}
39
40#[derive(Deserialize)]
41pub struct ModuleMapping {
42 pub module: String,
43 pub feature: String,
44}
45
46#[derive(Deserialize, Default)]
47pub struct Blocklist {
48 #[serde(default)]
49 pub classes: Vec<String>,
50 #[serde(default)]
51 pub structs: Vec<String>,
52 #[serde(default)]
54 pub functions: Vec<String>,
55}
56
57impl Blocklist {
58 pub fn function_tuples(&self) -> Vec<(String, String)> {
60 self.functions
61 .iter()
62 .filter_map(|entry| {
63 let (class, func) = entry.split_once('.')?;
64 Some((class.to_string(), func.to_string()))
65 })
66 .collect()
67 }
68}
69
70impl ProjectConfig {
71 pub fn load(root: &Path) -> Result<Self, String> {
73 let path = root.join(FILE_NAME);
74 let text = std::fs::read_to_string(&path)
75 .map_err(|e| format!("cannot read {}: {e}", path.display()))?;
76 toml::from_str(&text).map_err(|e| format!("cannot parse {}: {e}", path.display()))
77 }
78}
79
80pub struct ProjectLayout {
83 pub root: PathBuf,
85}
86
87impl ProjectLayout {
88 pub fn new(root: &Path) -> Self {
89 Self { root: root.to_path_buf() }
90 }
91
92 pub fn uproject(&self) -> Option<PathBuf> {
94 find_uproject(&self.root)
95 }
96
97 pub fn rust_workspace(&self) -> PathBuf {
99 self.root.join("Rust")
100 }
101
102 pub fn bindings_crate(&self) -> PathBuf {
104 self.rust_workspace().join("bindings")
105 }
106
107 pub fn cpp_generated(&self) -> PathBuf {
109 self.root.join("Plugins/Rusteal/Source/Rusteal/Generated")
110 }
111
112 pub fn uht_json(&self) -> PathBuf {
114 self.root.join("Intermediate/Rusteal/uht")
115 }
116
117 pub fn config_file(&self) -> PathBuf {
119 self.root.join(FILE_NAME)
120 }
121}
122
123pub fn find_uproject(dir: &Path) -> Option<PathBuf> {
125 std::fs::read_dir(dir)
126 .ok()?
127 .flatten()
128 .map(|entry| entry.path())
129 .find(|path| path.extension().is_some_and(|ext| ext == "uproject"))
130}
131
132pub fn find_project_root(start: &Path) -> Option<PathBuf> {
134 let start = start.canonicalize().ok()?;
135 start
136 .ancestors()
137 .find(|dir| find_uproject(dir).is_some())
138 .map(Path::to_path_buf)
139}