use std::{
env,
error::Error,
fmt,
fs::File,
io::{BufWriter, Write},
path::Path,
};
const RUSTC_MAX_ALIGN_EXP: u16 = 29;
fn main() -> Result<(), Box<dyn Error>> {
println!("cargo::rerun-if-changed=build.rs");
let ptr_width: u16 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")?
.parse::<u64>()?
.try_into()?;
let max_align_exp = (ptr_width - 2).min(RUSTC_MAX_ALIGN_EXP);
let out_dir = env::var_os("OUT_DIR").ok_or(env::VarError::NotPresent)?;
let out_dir = Path::new(&out_dir);
let mut f = BufWriter::new(File::create(out_dir.join("for_each_align.rs"))?);
write_for_each_align_macro(&mut f, max_align_exp)?;
Ok(())
}
fn write_for_each_align_macro(f: &mut impl Write, max_align_exp: u16) -> std::io::Result<()> {
write!(f, "macro_rules! for_each_align {{")?;
write!(f, "{}($($mac:tt)*) => {{", IndentLn(1))?;
write!(f, "{}$($mac)*! {{", IndentLn(2))?;
let ln = IndentLn(3);
for i in 0..=max_align_exp {
write!(f, "{ln}0b1")?;
for _ in 0..i {
write!(f, "0")?;
}
}
for i in (0..=2).rev() {
write!(f, "{}", IndentLn(i))?;
write!(f, "}}")?;
}
Ok(())
}
struct IndentLn(u8);
impl std::fmt::Display for IndentLn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f)?;
for _ in 0..self.0 {
write!(f, " ")?;
}
Ok(())
}
}