use std::collections::HashMap;
use std::str::FromStr;
use anyhow::Error as AnyError;
use regex::Error as RegexError;
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ConfgetError {
#[error("Invalid configuration specified: {0}")]
Config(String),
#[error("Could not parse the '{0}' file")]
FileFormat(String, #[source] AnyError),
#[error("Could not parse the '{0}' glob pattern")]
Glob(String, #[source] AnyError),
#[error("Internal confget error: {0}")]
Internal(String),
#[error("Could not read the input data")]
ReadData(#[source] AnyError),
#[error("Could not compile the '{0}' regular expression")]
Regex(String, #[source] RegexError),
#[error("Unrecognized backend type '{0}'")]
UnknownBackend(String),
}
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum BackendKind {
#[cfg(feature = "ini-nom")]
IniNom,
#[cfg(feature = "ini-regex")]
IniRE,
}
impl BackendKind {
#[cfg(feature = "ini-nom")]
pub const INI_NOM: &'static str = "ini-nom";
#[cfg(feature = "ini-regex")]
pub const INI_RE: &'static str = "ini-regex";
#[inline]
#[must_use]
pub const fn get_preferred_ini_backend() -> Self {
#[cfg(feature = "ini-nom")]
return Self::IniNom;
#[cfg(not(feature = "ini-nom"))]
#[cfg(feature = "ini-regex")]
return Self::IniRE;
}
#[inline]
#[must_use]
pub const fn get_preferred_ini_backend_name() -> &'static str {
#[cfg(feature = "ini-nom")]
return Self::INI_NOM;
#[cfg(not(feature = "ini-nom"))]
#[cfg(feature = "ini-regex")]
return Self::INI_RE;
}
}
impl FromStr for BackendKind {
type Err = ConfgetError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
#[cfg(feature = "ini-nom")]
Self::INI_NOM => Ok(Self::IniNom),
#[cfg(feature = "ini-regex")]
Self::INI_RE => Ok(Self::IniRE),
other => Err(ConfgetError::UnknownBackend(other.to_owned())),
}
}
}
impl AsRef<str> for BackendKind {
#[inline]
fn as_ref(&self) -> &str {
match *self {
#[cfg(feature = "ini-nom")]
Self::IniNom => Self::INI_NOM,
#[cfg(feature = "ini-regex")]
Self::IniRE => Self::INI_RE,
}
}
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
#[allow(clippy::struct_excessive_bools)]
pub struct Config {
pub backend: BackendKind,
pub encoding: String,
pub filename: Option<String>,
pub list_all: bool,
pub match_regex: bool,
pub match_var_names: bool,
pub match_var_values: Option<String>,
pub name_prefix: String,
pub name_suffix: String,
pub section: String,
pub section_override: bool,
pub section_specified: bool,
pub shell_escape: bool,
pub show_var_name: bool,
pub varnames: Vec<String>,
}
impl Default for Config {
#[inline]
fn default() -> Self {
Self {
backend: BackendKind::get_preferred_ini_backend(),
encoding: String::new(),
filename: None,
list_all: false,
match_regex: false,
match_var_names: false,
match_var_values: None,
name_prefix: String::new(),
name_suffix: String::new(),
section: String::new(),
section_override: false,
section_specified: false,
shell_escape: false,
show_var_name: false,
varnames: Vec::new(),
}
}
}
pub type SectionData = HashMap<String, String>;
pub type FileData = HashMap<String, SectionData>;