use std::collections::BTreeMap;
use std::path::Path;
use figment::{
Figment,
providers::{Format, Serialized, Toml},
};
use serde::{Deserialize, Serialize};
use strum_macros::{Display, EnumString};
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub fmt: FormatConfig,
pub check: CheckConfig,
pub warnings: BTreeMap<String, WarningConfig>,
}
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct FormatConfig {
pub rule: RuleFormatConfig,
pub meta: MetaFormatConfig,
pub patterns: PatternsFormatConfig,
}
#[derive(Display, Deserialize, Serialize, Debug, Clone, EnumString)]
#[serde(deny_unknown_fields)]
pub enum MetaValueType {
#[serde(rename = "string")]
#[strum(serialize = "string")]
String,
#[serde(rename = "integer")]
#[strum(serialize = "integer")]
Integer,
#[serde(rename = "float")]
#[strum(serialize = "float")]
Float,
#[serde(rename = "bool")]
#[strum(serialize = "bool")]
Bool,
#[serde(rename = "sha256")]
#[strum(serialize = "sha256")]
Sha256,
#[serde(rename = "sha1")]
#[strum(serialize = "sha1")]
Sha1,
#[serde(rename = "md5")]
#[strum(serialize = "md5")]
MD5,
#[serde(rename = "hash")]
#[strum(serialize = "hash")]
Hash,
}
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct CheckConfig {
pub metadata: BTreeMap<String, MetadataConfig>,
pub rule_name: RuleNameConfig,
pub tags: TagConfig,
}
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct TagConfig {
pub allowed: Vec<String>,
pub regexp: Option<String>,
#[serde(default)]
pub error: bool,
}
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct RuleNameConfig {
pub regexp: Option<String>,
#[serde(default)]
pub error: bool,
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct MetadataConfig {
#[serde(rename = "type")]
pub ty: MetaValueType,
pub regexp: Option<String>,
#[serde(default)]
pub required: bool,
#[serde(default)]
pub error: bool,
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct RuleFormatConfig {
pub indent_section_headers: bool,
pub indent_section_contents: bool,
pub indent_spaces: u8,
pub newline_before_curly_brace: bool,
pub empty_line_before_section_header: bool,
pub empty_line_after_section_header: bool,
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct MetaFormatConfig {
pub align_values: bool,
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct PatternsFormatConfig {
pub align_values: bool,
}
#[derive(Deserialize, Serialize, Debug, Default)]
#[serde(deny_unknown_fields)]
pub struct WarningConfig {
pub disabled: bool,
}
impl Default for RuleFormatConfig {
fn default() -> RuleFormatConfig {
RuleFormatConfig {
indent_section_headers: true,
indent_section_contents: true,
indent_spaces: 2,
newline_before_curly_brace: false,
empty_line_before_section_header: true,
empty_line_after_section_header: false,
}
}
}
impl Default for MetaFormatConfig {
fn default() -> MetaFormatConfig {
MetaFormatConfig { align_values: true }
}
}
impl Default for PatternsFormatConfig {
fn default() -> PatternsFormatConfig {
PatternsFormatConfig { align_values: true }
}
}
pub fn load_config_from_file(
config_file: &Path,
) -> Result<Config, Box<figment::Error>> {
let config: Config =
Figment::from(Serialized::defaults(Config::default()))
.merge(Toml::file_exact(config_file))
.extract()?;
Ok(config)
}