mod conf_parser;
pub use conf_parser::{
parse_config_bool, parse_config_u32, validate_profiles, InlineConfigParser,
InlineConfigParserError,
};
use once_cell::sync::Lazy;
use std::collections::HashMap;
mod natspec;
pub use natspec::NatSpec;
use crate::Config;
pub const INLINE_CONFIG_FUZZ_KEY: &str = "fuzz";
pub const INLINE_CONFIG_INVARIANT_KEY: &str = "invariant";
const INLINE_CONFIG_PREFIX: &str = "forge-config";
static INLINE_CONFIG_PREFIX_SELECTED_PROFILE: Lazy<String> = Lazy::new(|| {
let selected_profile = Config::selected_profile().to_string();
format!("{INLINE_CONFIG_PREFIX}:{selected_profile}.")
});
#[derive(thiserror::Error, Debug)]
#[error("Inline config error detected at {line}")]
pub struct InlineConfigError {
pub line: String,
pub source: InlineConfigParserError,
}
type InlineConfigKey = (String, String);
#[derive(Default, Debug, Clone)]
pub struct InlineConfig<T: 'static> {
configs: HashMap<InlineConfigKey, T>,
}
impl<T> InlineConfig<T> {
pub fn get<S: Into<String>>(&self, contract_id: S, fn_name: S) -> Option<&T> {
self.configs.get(&(contract_id.into(), fn_name.into()))
}
pub fn insert<S: Into<String>>(&mut self, contract_id: S, fn_name: S, config: T) {
self.configs.insert((contract_id.into(), fn_name.into()), config);
}
}
fn remove_whitespaces(s: &str) -> String {
s.chars().filter(|c| !c.is_whitespace()).collect()
}
#[cfg(test)]
mod tests {
use super::InlineConfigParserError;
use crate::InlineConfigError;
#[test]
fn can_format_inline_config_errors() {
let source = InlineConfigParserError::ParseBool("key".into(), "invalid-bool-value".into());
let line = "dir/TestContract.t.sol:FuzzContract".to_string();
let error = InlineConfigError { line: line.clone(), source };
let expected = format!("Inline config error detected at {line}");
assert_eq!(error.to_string(), expected);
}
}