#![allow(clippy::branches_sharing_code)]
use std::io::Write;
#[cfg(feature = "clap")]
use clap::Args;
#[cfg(feature = "clap")]
#[derive(Debug, Args)]
pub struct CodeGenArgs {
#[clap(short('o'), long, parse(from_os_str))]
output: std::path::PathBuf,
#[clap(long)]
check: bool,
}
#[cfg(feature = "clap")]
impl CodeGenArgs {
pub fn write_str(&self, content: &str) -> Result<(), Box<dyn std::error::Error>> {
write_str(content, &self.output, self.check)
}
}
pub fn write_str(
content: &str,
output: &std::path::Path,
check: bool,
) -> Result<(), Box<dyn std::error::Error>> {
if check {
let content: String = normalize_line_endings::normalized(content.chars()).collect();
let actual = std::fs::read_to_string(output)?;
let actual: String = normalize_line_endings::normalized(actual.chars()).collect();
if content == actual {
println!("Success");
} else {
let allocation = content.lines().count() * actual.lines().count();
if 1_000_000_000 < allocation {
eprintln!("{} out of sync (too big to diff)", output.display());
return Err(Box::new(CodeGenError));
} else {
let changeset = difference::Changeset::new(&actual, &content, "\n");
assert_ne!(changeset.distance, 0);
eprintln!("{} out of sync:", output.display());
eprintln!("{}", changeset);
return Err(Box::new(CodeGenError));
}
}
} else {
let mut file = std::io::BufWriter::new(std::fs::File::create(output)?);
write!(file, "{}", content)?;
}
Ok(())
}
#[cfg(feature = "clap")]
#[derive(Debug, Args)]
pub struct RustfmtArgs {
#[clap(long, parse(from_os_str))]
rustfmt_config: Option<std::path::PathBuf>,
}
#[cfg(feature = "clap")]
impl RustfmtArgs {
pub fn reformat(
&self,
text: impl std::fmt::Display,
) -> Result<String, Box<dyn std::error::Error>> {
rustfmt(text, self.rustfmt_config.as_deref())
}
}
pub fn rustfmt(
text: impl std::fmt::Display,
config: Option<&std::path::Path>,
) -> Result<String, Box<dyn std::error::Error>> {
let mut rustfmt = std::process::Command::new("rustfmt");
rustfmt
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped());
if let Some(config) = config {
rustfmt.arg("--config-path").arg(config);
}
let mut rustfmt = rustfmt.spawn()?;
write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
let output = rustfmt.wait_with_output()?;
let stdout = String::from_utf8(output.stdout)?;
Ok(stdout)
}
#[derive(Copy, Clone, Debug, derive_more::Display)]
#[display(fmt = "Code-gen failed")]
struct CodeGenError;
impl std::error::Error for CodeGenError {}