macro_rules! path_from_id {
($id_name:ident) => {{
format!(
"{}/rustifact_{}_{}.rs",
std::env::var("OUT_DIR").unwrap(),
std::env::var("CARGO_PKG_NAME").unwrap(),
stringify!($id_name),
)
}};
}
const DOC_HIDDEN: &'static str = "#[doc(hidden)]";
const MACRO_HEADER: &'static str = r#"
#[macro_export]
macro_rules! "#;
fn counting_entry_for(delta: i32, impl_id: &str, dim: usize) -> String {
format!(
" ({}, $($args:tt),+) => {{ rustifact::{}!({}, $($args),+) }};",
dim,
impl_id,
dim as i32 + delta,
)
}
macro_rules! write_counting {
($delta:expr, $id:ident, $id_impl:expr) => {
let path_str = path_from_id!($id);
let path = std::path::Path::new(&path_str);
let id = stringify!($id);
let id_impl = stringify!($id_impl);
let s = format!(
"{}\n{} {} {{\n{}\n}}",
DOC_HIDDEN,
MACRO_HEADER,
id,
(1..=NUM_DIMS)
.into_iter()
.map(|d| counting_entry_for($delta, id_impl, d))
.collect::<Vec<String>>()
.join("\n")
);
std::fs::write(&path, s).unwrap();
};
}
fn public_base_entry_for(id: &str) -> String {
format!(
"($id:ident, $t:ty, $data:expr) => {{ rustifact::{}!($id, $t : 1, $data); }};",
id
)
}
fn public_entry_for(dim: usize, const_static: &str, params_extra: &str) -> String {
format!(
" ($id:ident, $t:ty : {}, $data:expr) => {{ rustifact::__write_with!({}, {}, $id, $t, $data, {}) }};",
dim,
dim,
const_static,
params_extra
)
}
macro_rules! write_public {
($id:ident, $const_static:ident, $params_extra:expr, $doc:expr) => {
let path_str = path_from_id!($id);
let path = std::path::Path::new(&path_str);
let id = stringify!($id);
let const_static = stringify!($const_static);
let s = format!(
"#[doc = \"{}\"]\n{} {} {{\n{}\n{}\n}}",
$doc,
MACRO_HEADER,
id,
public_base_entry_for(id),
(1..=NUM_DIMS)
.into_iter()
.map(|d| public_entry_for(d, const_static, $params_extra))
.collect::<Vec<String>>()
.join("\n")
);
std::fs::write(&path, s).unwrap();
};
}
macro_rules! write_public_deprecated {
(
$id:ident, $const_static:ident, $deprec_version:literal, $deprec_note:literal,
$params_extra:expr, $doc:expr
) => {
let path_str = path_from_id!($id);
let path = std::path::Path::new(&path_str);
let id = stringify!($id);
let const_static = stringify!($const_static);
let deprecation_info = format!(
"#[deprecated(since = \"{}\", note = \"{}\")]",
$deprec_version, $deprec_note
);
let s = format!(
"#[doc = \"{}\"]\n{}\n{} {} {{\n{}\n{}\n}}",
$doc,
deprecation_info,
MACRO_HEADER,
id,
public_base_entry_for(id),
(1..=NUM_DIMS)
.into_iter()
.map(|d| public_entry_for(d, const_static, $params_extra))
.collect::<Vec<String>>()
.join("\n")
);
std::fs::write(&path, s).unwrap();
};
}
const NUM_DIMS: usize = 16;
fn main() {
write_counting!(-1, __vector_type, __vector_type_impl);
write_counting!(-1, __array_type, __array_type_impl);
write_counting!(-1, __assert_dim, __assert_dim_impl);
write_counting!(-1, __get_tokens_vector_fn, __get_tokens_vector_fn_impl);
write_counting!(-1, __get_tokens_array, __get_tokens_array_impl);
write_counting!(0, __write_with, __write_with_impl);
write_public!(
write_static_array,
static,
"__get_tokens_array, __array_type, __write_with_internal",
r#"Write an array to a static context.
Makes the array, array reference, or array slice available for import into the main crate via [`use_symbols`].
## Parameters
* `$id`: the name/identifier to give the exported array
* `$t`: the type of elements of the exported array will contain. Optionally followed by `: DIM`
where `DIM` is the dimension (1, 2, 3, ...) of the array. The dimension defaults to 1 when unspecified.
* `$data`: the contents of the array. May be an array, an array reference, or array slice.
## Further notes
* Must be called from a build script (build.rs) only."#
);
write_public!(
write_const_array,
const,
"__get_tokens_array, __array_type, __write_with_internal",
r#"Write an array to a const context.
Makes the array, array reference, or array slice available for import into the main crate via [`use_symbols`].
Stack allocated types (such as [`slice`]s and [`array`]s) may be returned.
## Parameters
* `$id`: the name/identifier to give the exported array
* `$t`: the type of elements of the exported array will contain. Optionally followed by `: DIM`
where `DIM` is the dimension (1, 2, 3, ...) of the array. The dimension defaults to 1 when unspecified.
* `$data`: the contents of the array. May be an array, an array reference, or array slice.
## Further notes
* Must be called from a build script (build.rs) only.
* If the array is large and referenced many times, this will lead to code bloat. In such a case,
consider carefully whether [`write_static_array`] would be more appropriate instead."#
);
write_public_deprecated!(
write_array_fn,
dummy,
"0.10.0",
"It seems that `write_array_fn!` only serves very rare use cases. If you disagree, please file an issue on Github.",
"__get_tokens_array, __array_type, __write_fn_with_internal",
r#"Write an array or vector to an array getter function.
Generates an array-returning function available for import into the main crate via [`use_symbols`].
## Parameters
* `$id`: the name/identifier to give the exported array-returning function.
* `$t`: the type of elements of the exported array will contain. Optionally followed by `: DIM`
where `DIM` is the dimension (1, 2, 3, ...) of the array. The dimension defaults to 1 when unspecified.
* `$data`: the contents of the array to be returned. May be an array, an array reference, or array slice.
## Further notes
* Must be called from a build script (build.rs) only.
* If the array elements are not heap allocated, consider using [`write_static_array`] or [`write_const_array`] instead."#
);
write_public_deprecated!(
write_vector_fn,
dummy,
"0.10.0",
"Use JaggedArray from the rustifact_extra crate instead for a proper static representation",
"__get_tokens_vector_fn, __vector_type, __write_fn_with_internal",
r#"Write an array or vector to a vector getter function.
Generates an array-returning function available for import into the main crate via [`use_symbols`].
## Parameters
* `$id`: the name/identifier to give the exported array-returning function.
* `$t`: the type of elements of the exported array will contain. Optionally followed by `: DIM`
where `DIM` is the dimension (1, 2, 3, ...) of the array. The dimension defaults to 1 when unspecified.
* `$data`: the contents of the vector to be returned. May be a `Vec`, an array, an array reference,
or array slice.
## Further notes
* Must be called from a build script (build.rs) only."#
);
}