use crate::vdf::VdfValue;
use indexmap::IndexMap;
impl VdfValue {
pub fn new_object() -> Self {
VdfValue::Object(IndexMap::new())
}
pub fn new_string(s: impl Into<String>) -> Self {
VdfValue::String(s.into())
}
pub fn get_value_by_path<T: AsRef<str>>(&self, path: &[T]) -> Option<&str> {
match self.get_by_path(path) {
Some(vdf_value) => match vdf_value.as_string() {
Some(value) => Some(value),
None => None,
},
None => None,
}
}
pub fn get_by_path<T: AsRef<str>>(&self, path: &[T]) -> Option<&VdfValue> {
if path.is_empty() {
return Some(self);
}
let mut current = self;
let mut index = 0;
while index < path.len() {
let key = &path[index];
if let VdfValue::Object(map) = current {
current = match map.get(key.as_ref()) {
Some(value) => value,
None => return None,
};
} else {
return None;
}
index += 1;
}
Some(current)
}
pub fn get<T: AsRef<str>>(&self, path: T) -> Option<&VdfValue> {
self.get_by_path(&[path])
}
pub fn get_value<T: AsRef<str>>(&self, path: T) -> Option<&str> {
self.get_value_by_path(&[path])
}
pub fn get_mut_by_path<T: AsRef<str>>(&mut self, path: &[T]) -> Option<&mut VdfValue> {
if path.is_empty() {
return Some(self);
}
let mut current = self;
let mut index = 0;
while index < path.len() {
let key = &path[index];
if let VdfValue::Object(map) = current {
current = match map.get_mut(key.as_ref()) {
Some(value) => value,
None => return None,
};
} else {
return None;
}
index += 1;
}
Some(current)
}
pub fn set_value_by_path<T: AsRef<str>>(&mut self, path: &[T], value: T) -> Result<(), String> {
self.set_by_path(path, VdfValue::String(value.as_ref().to_string()))
}
pub fn set_object_by_path<T: AsRef<str>>(
&mut self,
path: &[T],
value: IndexMap<String, Box<VdfValue>>,
) -> Result<(), String> {
self.set_by_path(path, VdfValue::Object(value))
}
pub fn set_by_path<T: AsRef<str>>(
&mut self,
path: &[T],
value: VdfValue,
) -> Result<(), String> {
if path.is_empty() {
*self = value;
return Ok(());
}
let parent_path = &path[..path.len() - 1];
let key = &path[path.len() - 1];
if let Some(parent) = self.get_mut_by_path(parent_path) {
if let VdfValue::Object(map) = parent {
map.insert(key.as_ref().to_string(), Box::new(value));
Ok(())
} else {
Err("Parent is not an object".to_string())
}
} else {
Err("Path not found".to_string())
}
}
pub fn path_exists(&self, path: &[&str]) -> bool {
self.get_by_path(path).is_some()
}
pub fn as_string(&self) -> Option<&str> {
if let VdfValue::String(s) = self {
Some(s)
} else {
None
}
}
pub fn as_object(&self) -> Option<&IndexMap<String, Box<VdfValue>>> {
if let VdfValue::Object(map) = self {
Some(map)
} else {
None
}
}
pub fn insert(&mut self, key: impl Into<String>, value: VdfValue) -> Result<(), String> {
if let VdfValue::Object(map) = self {
map.insert(key.into(), Box::new(value));
Ok(())
} else {
Err("Not an object".to_string())
}
}
}