use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use rlua::{Context, Lua};
use serde::{Deserialize, Serialize};
use serde_yaml::Mapping;
use serde_yaml::Value as YamlValue;
fn update_yaml_value_in_place(
doc: &mut YamlValue,
path: &str,
new_value: &str,
) -> Result<(), Box<dyn Error>> {
let path_segments: Vec<&str> = path.split('.').collect();
let mut current_node = doc;
for segment in path_segments {
match current_node {
YamlValue::Mapping(ref mut map) => {
if let Some(value) = map.get_mut(&YamlValue::String(segment.to_string())) {
current_node = value;
} else {
return Err(format!("Invalid path segment: {}", segment).into());
}
}
_ => return Err(format!("Invalid path segment: {}", segment).into()),
}
}
*current_node = YamlValue::String(new_value.to_string());
Ok(())
}
pub fn update_yaml_value(
file_path: &str,
path: &str,
new_value: &str,
) -> Result<(), Box<dyn Error>> {
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let mut doc: YamlValue = serde_yaml::from_str(&contents)?;
update_yaml_value_in_place(&mut doc, path, new_value)?;
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(file_path)?;
let updated_contents = serde_yaml::to_string(&doc)?;
file.write_all(updated_contents.as_bytes())?;
Ok(())
}
pub fn get_yaml_value(
file_path: &str,
yaml_key_path: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let yaml_data: YamlValue = serde_yaml::from_str(&contents)?;
let keys: Vec<&str> = yaml_key_path.split('.').collect();
let mut current_node = &yaml_data;
for key in keys.into_iter() {
if let YamlValue::Mapping(ref map) = current_node {
current_node = map
.get(&YamlValue::String(key.to_string()))
.ok_or_else(|| {
format!(
"Key '{}' not found in YAML key path: {}",
key, yaml_key_path
)
})?;
} else {
return Err(format!("Invalid YAML key path: {}", yaml_key_path).into());
}
}
if let YamlValue::String(value) = current_node {
Ok(value.clone())
} else {
Err("The retrieved YAML value is not a string.".into())
}
}