use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
fn main() {
cfg();
macros();
simd_macros();
println!("cargo:rerun-if-changed=build.rs");
}
fn cfg() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
let target_feature = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or_default();
let ok_arch = matches!(&*target_arch, "x86" | "x86_64");
let sse4_2_guaranteed = target_feature.split(',').any(|f| f == "sse4.2");
if sse4_2_guaranteed {
println!(r#"cargo:rustc-cfg=jetscii_sse4_2="yes""#);
} else if ok_arch {
println!(r#"cargo:rustc-cfg=jetscii_sse4_2="maybe""#);
} else {
println!(r#"cargo:rustc-cfg=jetscii_sse4_2="no""#);
}
}
fn macros() {
let mut base: PathBuf = env::var_os("OUT_DIR").unwrap().into();
base.push("src");
fs::create_dir_all(&base)
.unwrap_or_else(|e| panic!("Could not create directory {}: {}", base.display(), e));
base.push("macros.rs");
let mut f = File::create(&base)
.unwrap_or_else(|e| panic!("Could not create {}: {}", base.display(), e));
macros_bytes(&mut f, &base);
macros_ascii_chars(&mut f, &base);
}
fn macros_bytes(f: &mut File, base: &Path) {
let arms: String = (1..=16)
.map(|max| {
let args: Vec<_> = (0..max).map(|i| format!("$b{:02}:expr", i)).collect();
let args = args.join(", ");
let arg_values: Vec<_> = (0..max).map(|i| format!("$b{:02} as u8", i)).collect();
let mut array = arg_values.clone();
array.extend((max..16).map(|_| String::from("0")));
let array = array.join(", ");
let closure_body: Vec<_> = arg_values.iter().map(|n| format!("{} == c", n)).collect();
let closure = format!("|c| {}", closure_body.join(" || "));
format!(
"({}) => ($crate::Bytes::new([{}], {}, {}));\n",
args, array, max, closure
)
})
.collect();
write!(
f,
r#"
/// A convenience constructor for a [`Bytes`] that automatically
/// implements a fallback. Provide 1 to 16 characters.
#[macro_export]
macro_rules! bytes {{
{}}}
"#,
arms
).unwrap_or_else(|e| panic!("Could not write {}: {}", base.display(), e));
}
fn macros_ascii_chars(f: &mut File, base: &Path) {
let arms: String = (1..=16)
.map(|max| {
let args: Vec<_> = (0..max).map(|i| format!("$b{:02}:expr", i)).collect();
let args = args.join(", ");
let arg_values: Vec<_> = (0..max).map(|i| format!("$b{:02} as u8", i)).collect();
let mut array = arg_values.clone();
array.extend((max..16).map(|_| String::from("0")));
let array = array.join(", ");
let closure_body: Vec<_> = arg_values.iter().map(|n| format!("{} == c", n)).collect();
let closure = format!("|c| {}", closure_body.join(" || "));
format!(
"({}) => ($crate::AsciiChars::new([{}], {}, {}));\n",
args, array, max, closure
)
})
.collect();
write!(
f,
r#"
/// A convenience constructor for an [`AsciiChars`] that automatically
/// implements a fallback. Provide 1 to 16 characters.
#[macro_export]
macro_rules! ascii_chars {{
{}}}
"#,
arms
).unwrap_or_else(|e| panic!("Could not write {}: {}", base.display(), e));
}
fn simd_macros() {
let mut base: PathBuf = env::var_os("OUT_DIR").unwrap().into();
base.push("src");
fs::create_dir_all(&base)
.unwrap_or_else(|e| panic!("Could not create directory {}: {}", base.display(), e));
base.push("simd_macros.rs");
let mut f = File::create(&base)
.unwrap_or_else(|e| panic!("Could not create {}: {}", base.display(), e));
let arms: String = (1..=16)
.map(|max| {
let args: Vec<_> = (0..max).map(|i| format!("$b{:02}:expr", i)).collect();
let args = args.join(", ");
let mut array: Vec<_> = (0..max).map(|i| format!("$b{:02}", i)).collect();
array.extend((max..16).map(|_| String::from("0")));
let array = array.join(", ");
format!(
"({}) => ($crate::simd::Bytes::new([{}], {}));\n",
args, array, max
)
})
.collect();
write!(
&mut f,
r#"
#[allow(unused_macros)]
macro_rules! simd_bytes {{
{}}}
"#,
arms
).unwrap_or_else(|e| panic!("Could not write {}: {}", base.display(), e));
}