use super::prelude::*;
use crate as nu_protocol;
use std::collections::HashMap;
#[derive(Clone, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct PluginGcConfigs {
pub default: PluginGcConfig,
pub plugins: HashMap<String, PluginGcConfig>,
}
impl PluginGcConfigs {
pub fn get(&self, plugin_name: &str) -> &PluginGcConfig {
self.plugins.get(plugin_name).unwrap_or(&self.default)
}
}
impl UpdateFromValue for PluginGcConfigs {
fn update<'a>(
&mut self,
value: &'a Value,
path: &mut ConfigPath<'a>,
errors: &mut ConfigErrors,
) {
let Value::Record { val: record, .. } = value else {
errors.type_mismatch(path, Type::record(), value);
return;
};
for (col, val) in record.iter() {
let path = &mut path.push(col);
match col.as_str() {
"default" => self.default.update(val, path, errors),
"plugins" => self.plugins.update(val, path, errors),
_ => errors.unknown_option(path, val),
}
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PluginGcConfig {
pub enabled: bool,
pub stop_after: i64,
}
impl Default for PluginGcConfig {
fn default() -> Self {
PluginGcConfig {
enabled: true,
stop_after: 10_000_000_000, }
}
}
impl IntoValue for PluginGcConfig {
fn into_value(self, span: Span) -> Value {
record! {
"enabled" => self.enabled.into_value(span),
"stop_after" => Value::duration(self.stop_after, span),
}
.into_value(span)
}
}
impl UpdateFromValue for PluginGcConfig {
fn update<'a>(
&mut self,
value: &'a Value,
path: &mut ConfigPath<'a>,
errors: &mut ConfigErrors,
) {
let Value::Record { val: record, .. } = value else {
errors.type_mismatch(path, Type::record(), value);
return;
};
for (col, val) in record.iter() {
let path = &mut path.push(col);
match col.as_str() {
"enabled" => self.enabled.update(val, path, errors),
"stop_after" => {
if let Ok(duration) = val.as_duration() {
if duration >= 0 {
self.stop_after = duration;
} else {
errors.invalid_value(path, "a non-negative duration", val);
}
} else {
errors.type_mismatch(path, Type::Duration, val);
}
}
_ => errors.unknown_option(path, val),
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{record, Config, Span};
fn test_pair() -> (PluginGcConfigs, Value) {
(
PluginGcConfigs {
default: PluginGcConfig {
enabled: true,
stop_after: 30_000_000_000,
},
plugins: [(
"my_plugin".to_owned(),
PluginGcConfig {
enabled: false,
stop_after: 0,
},
)]
.into_iter()
.collect(),
},
Value::test_record(record! {
"default" => Value::test_record(record! {
"enabled" => Value::test_bool(true),
"stop_after" => Value::test_duration(30_000_000_000),
}),
"plugins" => Value::test_record(record! {
"my_plugin" => Value::test_record(record! {
"enabled" => Value::test_bool(false),
"stop_after" => Value::test_duration(0),
}),
}),
}),
)
}
#[test]
fn update() {
let (expected, input) = test_pair();
let config = Config::default();
let mut errors = ConfigErrors::new(&config);
let mut result = PluginGcConfigs::default();
result.update(&input, &mut ConfigPath::new(), &mut errors);
assert!(errors.is_empty(), "errors: {errors:#?}");
assert_eq!(expected, result);
}
#[test]
fn reconstruct() {
let (input, expected) = test_pair();
assert_eq!(expected, input.into_value(Span::test_data()));
}
}