use std::env;
fn is_power_of_2(n: usize) -> bool {
n > 0 && (n & (n - 1)) == 0
}
fn next_power_of_2(n: usize) -> usize {
if n == 0 {
return 1;
}
if is_power_of_2(n) {
return n;
}
let mut v = n;
v -= 1;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
#[cfg(target_pointer_width = "64")]
{
v |= v >> 32;
}
v + 1
}
fn main() {
let has_alloc = env::var("CARGO_FEATURE_ALLOC").is_ok();
let has_heapless = env::var("CARGO_FEATURE_HEAPLESS").is_ok();
let has_std = env::var("CARGO_FEATURE_STD").is_ok();
if !has_alloc && !has_heapless && !has_std {
eprintln!("error: Either the `alloc` or `heapless` feature must be enabled");
eprintln!("\ndbc-rs requires one of the following features:");
eprintln!(" - `alloc`: Heap-allocated collections via alloc crate");
eprintln!(" - `heapless`: Stack-allocated, bounded collections");
eprintln!(" - `std`: Includes alloc + standard library features (default)");
eprintln!("\nAdd to Cargo.toml:");
eprintln!(" [dependencies]");
eprintln!(
" dbc-rs = {{ version = \"...\", default-features = false, features = [\"alloc\"] }}"
);
eprintln!(" # OR");
eprintln!(
" dbc-rs = {{ version = \"...\", default-features = false, features = [\"heapless\"] }}"
);
std::process::exit(1);
}
let max_signals = env::var("DBC_MAX_SIGNALS_PER_MESSAGE")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(256);
let max_messages = env::var("DBC_MAX_MESSAGES")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(8192);
let max_nodes = env::var("DBC_MAX_NODES")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(256);
let max_value_descriptions = env::var("DBC_MAX_VALUE_DESCRIPTIONS")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(64);
let max_name_size = env::var("DBC_MAX_NAME_SIZE")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(32);
let max_extended_multiplexing = env::var("DBC_MAX_EXTENDED_MULTIPLEXING")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(512);
if has_heapless {
let heapless_constants = [
("DBC_MAX_MESSAGES", max_messages, "MAX_MESSAGES"),
(
"DBC_MAX_SIGNALS_PER_MESSAGE",
max_signals,
"MAX_SIGNALS_PER_MESSAGE",
),
("DBC_MAX_NODES", max_nodes, "MAX_NODES"),
("DBC_MAX_NAME_SIZE", max_name_size, "MAX_NAME_SIZE"),
(
"DBC_MAX_EXTENDED_MULTIPLEXING",
max_extended_multiplexing,
"MAX_EXTENDED_MULTIPLEXING",
),
];
for (env_var, value, const_name) in heapless_constants.iter() {
if !is_power_of_2(*value) {
eprintln!(
"error: {} must be a power of 2 when using `heapless` feature",
const_name
);
eprintln!(" Current value: {} (set via {}={})", value, env_var, value);
eprintln!(
" {} is used with heapless collections which require power-of-2 capacities.",
const_name
);
eprintln!(
"\nValid power-of-2 values: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, ..."
);
eprintln!("\nExample: Set {} to a power of 2:", env_var);
eprintln!(" {}={} cargo build ...", env_var, next_power_of_2(*value));
std::process::exit(1);
}
}
}
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = std::path::Path::new(&out_dir).join("limits.rs");
std::fs::write(
&dest_path,
format!(
"#[allow(dead_code)]\npub const MAX_SIGNALS_PER_MESSAGE: usize = {};\n#[allow(dead_code)]\npub const MAX_MESSAGES: usize = {};\n#[allow(dead_code)]\npub const MAX_NODES: usize = {};\n#[allow(dead_code)]\npub const MAX_VALUE_DESCRIPTIONS: usize = {};\n#[allow(dead_code)]\npub const MAX_NAME_SIZE: usize = {};\n#[allow(dead_code)]\npub const MAX_EXTENDED_MULTIPLEXING: usize = {};",
max_signals, max_messages, max_nodes, max_value_descriptions, max_name_size, max_extended_multiplexing
),
)
.unwrap();
println!("cargo:rerun-if-env-changed=DBC_MAX_SIGNALS_PER_MESSAGE");
println!("cargo:rerun-if-env-changed=DBC_MAX_MESSAGES");
println!("cargo:rerun-if-env-changed=DBC_MAX_NODES");
println!("cargo:rerun-if-env-changed=DBC_MAX_VALUE_DESCRIPTIONS");
println!("cargo:rerun-if-env-changed=DBC_MAX_NAME_SIZE");
println!("cargo:rerun-if-env-changed=DBC_MAX_EXTENDED_MULTIPLEXING");
}