static GEN_TRAITS: &[&str] = &[
"Debug",
"Display",
"LowerExp",
"LowerHex",
"Octal",
"Pointer",
"UpperExp",
"UpperHex"
];
static GENERATED_WARNING: &str = "\
// === === === === === === Warning === === === === === === //
// This file has been GENERATED by the BUILD SCRIPT. Any //
// modifications will be DISCARDED when switching to a //
// different version/release channel/target platform of //
// the Rust toolchain or if the build script receives an //
// update. //
// === === === === === === === === === === === === === === //
";
use std::{env, fs, path::PathBuf, io::Write};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let crate_dir = PathBuf::from(env::var_os("OUT_DIR")
.expect("Failed to retreive output directory (is Cargo broken?)"));
let mut file = fs::File::create(crate_dir.join("BUILDSCRIPT_GENERATED_only_adapters.rs")).unwrap();
file.write_all(generate_only_adapters_file().as_bytes()).unwrap();
let mut file = fs::File::create(crate_dir.join("BUILDSCRIPT_GENERATED_fmt_adapters.rs")).unwrap();
file.write_all(generate_fmt_adapters_file().as_bytes()).unwrap();
}
fn generate_only_adapters_file() -> String {
let mut snippets = Vec::<String>::with_capacity(GEN_TRAITS.len() + 1);
snippets.push(GENERATED_WARNING.to_string());
for tr in GEN_TRAITS {
snippets.push(mk_only(tr));
}
snippets.join("\n")
}
fn generate_fmt_adapters_file() -> String {
let mut snippets = Vec::<String>::with_capacity(GEN_TRAITS.len() + 1);
snippets.push(GENERATED_WARNING.to_string());
for trd in GEN_TRAITS {
for trs in GEN_TRAITS {
if trd == trs {continue;}
snippets.push(mk_adapter(trd, trs));
}
}
snippets.join("\n")
}
fn mk_only(tr: &str) -> String {
format!("\
/// Only implements the `{tr}` formatting trait despite any other trait being implemented on `T`.
#[repr(transparent)]
pub struct Only{tr}<T: {tr}> (pub T);
impl<T: {tr}> From<T> for Only{tr}<T> {{
#[inline(always)]
fn from(op: T) -> Self {{
Self(op)
}}
}}
impl<T: {tr}> {tr} for Only{tr}<T> {{
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {{
self.0.fmt(f)
}}
}}
impl<T: {tr}> Only{tr}<T> {{
/// Consumes the adapter and returns the wrapped value.
#[inline(always)]
pub fn into_inner(self) -> T {{
self.0
}}
}}",
tr = tr
)
}
fn mk_adapter(dst_trait: &str, src_trait: &str) -> String {
format!("\
/// Provides `{trd}` formatting by using the result of invoking `{trs}` formatting.
#[repr(transparent)]
pub struct {trd}From{trs}<T: {trs}> (pub T);
impl<T: {trs}> From<T> for {trd}From{trs}<T> {{
#[inline(always)]
fn from(op: T) -> Self {{
Self(op)
}}
}}
impl<T: {trs}> {trd} for {trd}From{trs}<T> {{
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {{
{trs}::fmt(&self.0, f)
}}
}}
impl<T: {trs}> {trd}From{trs}<T> {{
/// Consumes the adapter and returns the wrapped value.
#[inline(always)]
pub fn into_inner(self) -> T {{
self.0
}}
}}",
trs = src_trait,
trd = dst_trait
)
}