|
1 | | -use eyre::ContextCompat; |
| 1 | +use eyre::{Context, ContextCompat}; |
2 | 2 | use planus_types::{ast::IntegerType, intermediate::DeclarationKind}; |
3 | | -use std::{env::set_current_dir, fs, path::Path}; |
| 3 | +use std::{ |
| 4 | + env::set_current_dir, |
| 5 | + fs, |
| 6 | + io::Write, |
| 7 | + path::Path, |
| 8 | + process::{Command, Stdio}, |
| 9 | +}; |
4 | 10 |
|
5 | 11 | use crate::{ |
6 | 12 | enums::EnumBindGenerator, structs::StructBindGenerator, table::TableBindGenerator, |
@@ -80,6 +86,46 @@ fn camel_to_snake(input: &str) -> String { |
80 | 86 | snake_case |
81 | 87 | } |
82 | 88 |
|
| 89 | +/// Taken from <https://github.com/planus-org/planus/blob/main/crates/planus-codegen/src/rust/mod.rs#L1014> |
| 90 | +/// |
| 91 | +/// This formats a string using `rustfmt` (using Rust 2024 and not 2021) |
| 92 | +fn format_string(s: &str) -> eyre::Result<String> { |
| 93 | + let mut child = Command::new("rustfmt"); |
| 94 | + |
| 95 | + child |
| 96 | + .arg("--edition=2024") |
| 97 | + .stdin(Stdio::piped()) |
| 98 | + .stdout(Stdio::piped()) |
| 99 | + .stderr(Stdio::piped()); |
| 100 | + |
| 101 | + let mut child = child |
| 102 | + .spawn() |
| 103 | + .wrap_err("Unable to spawn rustfmt. Perhaps it is not installed?")?; |
| 104 | + |
| 105 | + { |
| 106 | + let child_stdin = child.stdin.as_mut().unwrap(); |
| 107 | + child_stdin |
| 108 | + .write_all(s.as_bytes()) |
| 109 | + .wrap_err("Unable to write the file to rustfmt")?; |
| 110 | + } |
| 111 | + |
| 112 | + let output = child |
| 113 | + .wait_with_output() |
| 114 | + .wrap_err("Unable to get the formatted file back from rustfmt")?; |
| 115 | + |
| 116 | + if output.status.success() && output.stderr.is_empty() { |
| 117 | + Ok(String::from_utf8_lossy(&output.stdout).into_owned()) |
| 118 | + } else if output.stderr.is_empty() { |
| 119 | + eyre::bail!("rustfmt failed with exit code {}", output.status); |
| 120 | + } else { |
| 121 | + eyre::bail!( |
| 122 | + "rustfmt failed with exit code {} and message:\n{}", |
| 123 | + output.status, |
| 124 | + String::from_utf8_lossy(&output.stderr).into_owned(), |
| 125 | + ) |
| 126 | + } |
| 127 | +} |
| 128 | + |
83 | 129 | fn main() -> eyre::Result<()> { |
84 | 130 | set_current_dir(env!("CARGO_MANIFEST_DIR")).unwrap(); |
85 | 131 |
|
@@ -121,6 +167,11 @@ fn main() -> eyre::Result<()> { |
121 | 167 | // generate custom code |
122 | 168 | for (path, item) in &declarations.declarations { |
123 | 169 | let item_name = path.0.last().unwrap().as_str(); |
| 170 | + if item_name == "Float" { |
| 171 | + // Special case for Float (we always inline Float into Py<PyFloat>) |
| 172 | + continue; |
| 173 | + } |
| 174 | + |
124 | 175 | let mut file_name = camel_to_snake(item_name); |
125 | 176 |
|
126 | 177 | let file_contents = match &item.kind { |
@@ -153,7 +204,10 @@ fn main() -> eyre::Result<()> { |
153 | 204 | ); |
154 | 205 | file_name.push_str(".rs"); |
155 | 206 |
|
156 | | - fs::write(python_folder.join(&file_name), file_contents.join("\n"))?; |
| 207 | + fs::write( |
| 208 | + python_folder.join(&file_name), |
| 209 | + format_string(&file_contents.join("\n"))?, |
| 210 | + )?; |
157 | 211 | python_files.push(file_name); |
158 | 212 | } |
159 | 213 |
|
@@ -185,7 +239,7 @@ fn main() -> eyre::Result<()> { |
185 | 239 | .replace("::serde::Serialize,", "") |
186 | 240 | .replace("::serde::Deserialize,", ""); |
187 | 241 |
|
188 | | - fs::write(OUT_FILE, generated_planus.as_bytes())?; |
| 242 | + fs::write(OUT_FILE, format_string(&generated_planus)?.as_bytes())?; |
189 | 243 |
|
190 | 244 | class_inject::classes_to_lib_rs(class_names)?; |
191 | 245 | pyi::generator(&declarations.declarations)?; |
|
0 commit comments