111 lines
3.5 KiB
Rust
111 lines
3.5 KiB
Rust
#![doc = include_str!("../README.md")]
|
|
//! ## Feature Flags
|
|
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
|
|
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
|
#![cfg_attr(not(feature = "build"), no_std)]
|
|
#![deny(missing_docs, rust_2018_idioms)]
|
|
|
|
#[cfg(feature = "build")]
|
|
mod generate;
|
|
#[cfg(feature = "build")]
|
|
pub use generate::{generate_config, Error, Validator, Value};
|
|
|
|
/// Parse the value of an environment variable as a [bool] at compile time.
|
|
#[macro_export]
|
|
macro_rules! esp_config_bool {
|
|
( $var:expr ) => {
|
|
match env!($var).as_bytes() {
|
|
b"true" => true,
|
|
b"false" => false,
|
|
_ => ::core::panic!("boolean value must be either 'true' or 'false'"),
|
|
}
|
|
};
|
|
}
|
|
|
|
// TODO: From 1.82 on, we can use `<$ty>::from_str_radix(env!($var), 10)`
|
|
/// Parse the value of an environment variable as an integer at compile time.
|
|
#[macro_export]
|
|
macro_rules! esp_config_int {
|
|
( $ty:ty, $var:expr ) => {
|
|
const {
|
|
const BYTES: &[u8] = env!($var).as_bytes();
|
|
$crate::esp_config_int_parse!($ty, BYTES)
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Get the string value of an environment variable at compile time.
|
|
#[macro_export]
|
|
macro_rules! esp_config_str {
|
|
( $var:expr ) => {
|
|
env!($var)
|
|
};
|
|
}
|
|
|
|
/// Parse a string like "777" into an integer, which _can_ be used in a `const`
|
|
/// context
|
|
#[doc(hidden)] // To avoid confusion with `esp_config_int`, hide this in the docs
|
|
#[macro_export]
|
|
macro_rules! esp_config_int_parse {
|
|
( $ty:ty, $bytes:expr ) => {{
|
|
let mut bytes = $bytes;
|
|
let mut val: $ty = 0;
|
|
let mut sign_seen = false;
|
|
let mut is_negative = false;
|
|
|
|
while let [byte, rest @ ..] = bytes {
|
|
match *byte {
|
|
b'0'..=b'9' => {
|
|
val = val * 10 + (*byte - b'0') as $ty;
|
|
}
|
|
b'-' | b'+' if !sign_seen => {
|
|
is_negative = *byte == b'-';
|
|
sign_seen = true;
|
|
}
|
|
_ => ::core::panic!("invalid character encountered while parsing integer"),
|
|
}
|
|
|
|
bytes = rest;
|
|
}
|
|
|
|
if is_negative {
|
|
let original = val;
|
|
// Subtract the value twice to get a negative:
|
|
val -= original;
|
|
val -= original;
|
|
}
|
|
|
|
val
|
|
}};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
// We can only test success in the const context
|
|
const _: () = {
|
|
core::assert!(esp_config_int_parse!(i64, "-77777".as_bytes()) == -77777);
|
|
core::assert!(esp_config_int_parse!(isize, "-7777".as_bytes()) == -7777);
|
|
core::assert!(esp_config_int_parse!(i32, "-999".as_bytes()) == -999);
|
|
core::assert!(esp_config_int_parse!(i16, "-99".as_bytes()) == -99);
|
|
core::assert!(esp_config_int_parse!(i8, "-9".as_bytes()) == -9);
|
|
|
|
core::assert!(esp_config_int_parse!(u64, "77777".as_bytes()) == 77777);
|
|
core::assert!(esp_config_int_parse!(usize, "7777".as_bytes()) == 7777);
|
|
core::assert!(esp_config_int_parse!(u32, "999".as_bytes()) == 999);
|
|
core::assert!(esp_config_int_parse!(u16, "99".as_bytes()) == 99);
|
|
core::assert!(esp_config_int_parse!(u8, "9".as_bytes()) == 9);
|
|
};
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn test_expect_positive() {
|
|
esp_config_int_parse!(u8, "-5".as_bytes());
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn test_invalid_digit() {
|
|
esp_config_int_parse!(u32, "a".as_bytes());
|
|
}
|
|
}
|