165 lines
5.0 KiB
Rust
165 lines
5.0 KiB
Rust
use crate::{Record, ShellError, Span, Value};
|
|
use std::{collections::HashMap, fmt::Display, str::FromStr, sync::Arc};
|
|
|
|
pub(super) trait ReconstructVal {
|
|
fn reconstruct_value(&self, span: Span) -> Value;
|
|
}
|
|
|
|
pub(super) fn process_string_enum<T, E>(
|
|
config_point: &mut T,
|
|
config_path: &[&str],
|
|
value: &mut Value,
|
|
errors: &mut Vec<ShellError>,
|
|
) where
|
|
T: FromStr<Err = E> + ReconstructVal,
|
|
E: Display,
|
|
{
|
|
let span = value.span();
|
|
if let Ok(v) = value.coerce_str() {
|
|
match v.parse() {
|
|
Ok(format) => {
|
|
*config_point = format;
|
|
}
|
|
Err(err) => {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: format!(
|
|
"unrecognized $env.config.{} option '{v}'",
|
|
config_path.join(".")
|
|
),
|
|
span: Some(span),
|
|
help: Some(err.to_string()),
|
|
inner: vec![],
|
|
});
|
|
// Reconstruct
|
|
*value = config_point.reconstruct_value(span);
|
|
}
|
|
}
|
|
} else {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: format!("$env.config.{} should be a string", config_path.join(".")),
|
|
span: Some(span),
|
|
help: Some("This value will be ignored.".into()),
|
|
inner: vec![],
|
|
});
|
|
// Reconstruct
|
|
*value = config_point.reconstruct_value(span);
|
|
}
|
|
}
|
|
|
|
pub(super) fn process_bool_config(
|
|
value: &mut Value,
|
|
errors: &mut Vec<ShellError>,
|
|
config_point: &mut bool,
|
|
) {
|
|
if let Ok(b) = value.as_bool() {
|
|
*config_point = b;
|
|
} else {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: "should be a bool".to_string(),
|
|
span: Some(value.span()),
|
|
help: Some("This value will be ignored.".into()),
|
|
inner: vec![],
|
|
});
|
|
// Reconstruct
|
|
*value = Value::bool(*config_point, value.span());
|
|
}
|
|
}
|
|
|
|
pub(super) fn process_int_config(
|
|
value: &mut Value,
|
|
errors: &mut Vec<ShellError>,
|
|
config_point: &mut i64,
|
|
) {
|
|
if let Ok(b) = value.as_int() {
|
|
*config_point = b;
|
|
} else {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: "should be an int".into(),
|
|
span: Some(value.span()),
|
|
help: Some("This value will be ignored.".into()),
|
|
inner: vec![],
|
|
});
|
|
// Reconstruct
|
|
*value = Value::int(*config_point, value.span());
|
|
}
|
|
}
|
|
|
|
pub(super) fn process_opt_str_config(
|
|
value: &mut Value,
|
|
errors: &mut Vec<ShellError>,
|
|
config_point: &mut Option<Arc<str>>,
|
|
) {
|
|
if value.is_nothing() {
|
|
*config_point = None;
|
|
return;
|
|
}
|
|
match value.coerce_str() {
|
|
Ok(s) => *config_point = Some(s.into()),
|
|
Err(e) => {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: e.to_string(),
|
|
span: Some(value.span()),
|
|
help: Some("This value will be ignored.".into()),
|
|
inner: vec![],
|
|
});
|
|
// Reconstruct
|
|
*value = match config_point {
|
|
Some(s) => Value::string(s.as_ref(), value.span()),
|
|
None => Value::nothing(value.span()),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(super) fn report_invalid_key(keys: &[&str], span: Span, errors: &mut Vec<ShellError>) {
|
|
// Because Value::Record discards all of the spans of its
|
|
// column names (by storing them as Strings), the key name cannot be provided
|
|
// as a value, even in key errors.
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: format!(
|
|
"$env.config.{} is an unknown config setting",
|
|
keys.join(".")
|
|
),
|
|
span: Some(span),
|
|
help: Some("This value will not appear in your $env.config record.".into()),
|
|
inner: vec![],
|
|
});
|
|
}
|
|
|
|
pub(super) fn report_invalid_value(msg: &str, span: Span, errors: &mut Vec<ShellError>) {
|
|
errors.push(ShellError::GenericError {
|
|
error: "Error while applying config changes".into(),
|
|
msg: msg.into(),
|
|
span: Some(span),
|
|
help: Some("This value will be ignored.".into()),
|
|
inner: vec![],
|
|
});
|
|
}
|
|
|
|
pub(super) fn create_map(value: &Value) -> Result<HashMap<String, Value>, ShellError> {
|
|
Ok(value
|
|
.as_record()?
|
|
.iter()
|
|
.map(|(k, v)| (k.clone(), v.clone()))
|
|
.collect())
|
|
}
|
|
|
|
pub fn extract_value<'record>(
|
|
name: &str,
|
|
record: &'record Record,
|
|
span: Span,
|
|
) -> Result<&'record Value, ShellError> {
|
|
record
|
|
.get(name)
|
|
.ok_or_else(|| ShellError::MissingConfigValue {
|
|
missing_value: name.to_string(),
|
|
span,
|
|
})
|
|
}
|