#![doc = include_str!("../README.md")] //! ## Feature Flags #![doc = document_features::document_features!(feature_label = r#"{feature}"#)] #![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()); } }