use crate::cli::styles::{info, reset};
use figment::{Metadata, Profile, Source};
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Setting {
pub source: String,
pub line_number: usize,
pub args: Vec<String>,
}
impl Setting {
pub(crate) fn first_arg(&self) -> String {
self.args.first().cloned().unwrap_or_else(String::new)
}
}
pub(super) struct ValueProvider<'a> {
key: &'a String,
value: &'a Setting,
profile: &'a Profile,
}
impl<'a> ValueProvider<'a> {
pub(super) fn new(key: &'a String, value: &'a Setting, profile: &'a Profile) -> Self {
Self {
key,
value,
profile,
}
}
}
impl figment::Provider for ValueProvider<'_> {
fn metadata(&self) -> figment::Metadata {
Metadata::from(
"configuration file",
Source::Custom(format!(
"{src} (line {line})",
src = self.value.source,
line = self.value.line_number
)),
)
.interpolater(|profile, path| {
let key = path.to_vec();
format!(
"key `{INFO}{key}{RESET}` of host `{INFO}{profile}{RESET}`",
key = key.join("."),
INFO = info(),
RESET = reset(),
)
})
}
fn data(
&self,
) -> std::result::Result<
figment::value::Map<figment::Profile, figment::value::Dict>,
figment::Error,
> {
use figment::value::{Dict, Empty, Value};
let mut dict = Dict::new();
let value: Value = match self.value.args.len() {
0 => Empty::Unit.into(),
1 => self.value.args.first().unwrap().clone().into(),
_ => self.value.args.clone().into(),
};
let _ = dict.insert(self.key.clone(), value);
Ok(self.profile.collect(dict))
}
fn profile(&self) -> Option<Profile> {
Some(self.profile.clone())
}
}