use crate::{VmfError, VmfResult};
use indexmap::IndexMap;
pub trait To01String {
fn to_01_string(self) -> String;
}
impl To01String for bool {
fn to_01_string(self) -> String {
if self {
"1".to_string()
} else {
"0".to_string()
}
}
}
#[inline(always)]
pub(crate) fn get_key_ref<'a>(map: &'a IndexMap<String, String>, key: &str) -> VmfResult<&'a str> {
map.get(key)
.map(|s| s.as_str()) .ok_or_else(|| VmfError::InvalidFormat(format!("'{}' key not found", key)))
}
#[inline(always)]
pub(crate) fn take_key_owned(map: &mut IndexMap<String, String>, key: &str) -> VmfResult<String> {
map.swap_remove(key)
.ok_or_else(|| VmfError::InvalidFormat(format!("'{}' key not found", key)))
}
#[inline(always)]
pub(crate) fn take_and_parse_key<T>(map: &mut IndexMap<String, String>, key: &str) -> VmfResult<T>
where
T: std::str::FromStr,
VmfError: From<(T::Err, String)>,
{
let value_string = take_key_owned(map, key)?;
value_string
.parse::<T>()
.map_err(|e| VmfError::from((e, key.to_string())))
}
#[inline(always)]
pub(crate) fn take_key_or_default(
map: &mut IndexMap<String, String>,
key: &str,
default: String,
) -> String {
map.swap_remove(key).unwrap_or(default)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::VmfError;
use indexmap::IndexMap;
#[test]
fn get_key_ref_existing_key() {
let mut map = IndexMap::new();
map.insert("test_key".to_string(), "test_value".to_string());
let value = get_key_ref(&map, "test_key").unwrap();
assert_eq!(value, "test_value");
assert!(map.contains_key("test_key"));
}
#[test]
fn get_key_ref_missing_key() {
let map = IndexMap::<String, String>::new();
let result = get_key_ref(&map, "test_key");
assert!(matches!(result, Err(VmfError::InvalidFormat(_))));
if let Err(VmfError::InvalidFormat(msg)) = result {
assert!(msg.contains("'test_key' key not found"));
}
}
#[test]
fn take_key_owned_existing_key() {
let mut map = IndexMap::new();
map.insert("test_key".to_string(), "test_value".to_string());
let value = take_key_owned(&mut map, "test_key").unwrap();
assert_eq!(value, "test_value");
assert!(!map.contains_key("test_key"));
}
#[test]
fn take_key_owned_missing_key() {
let mut map = IndexMap::<String, String>::new();
let result = take_key_owned(&mut map, "test_key");
assert!(matches!(result, Err(VmfError::InvalidFormat(_))));
if let Err(VmfError::InvalidFormat(msg)) = result {
assert!(msg.contains("'test_key' key not found"));
}
}
#[test]
fn take_key_or_default_existing_key() {
let mut map = IndexMap::new();
map.insert("test_key".to_string(), "test_value".to_string());
let default_val = "default".to_string();
let value = take_key_or_default(&mut map, "test_key", default_val.clone());
assert_eq!(value, "test_value");
assert!(!map.contains_key("test_key"));
}
#[test]
fn take_key_or_default_missing_key() {
let mut map = IndexMap::<String, String>::new();
let default_val = "default".to_string();
let value = take_key_or_default(&mut map, "test_key", default_val.clone());
assert_eq!(value, default_val);
assert!(map.is_empty());
}
#[test]
fn take_and_parse_key_valid_value() {
let mut map = IndexMap::new();
map.insert("test_key".to_string(), "123".to_string());
let value = take_and_parse_key::<i32>(&mut map, "test_key").unwrap();
assert_eq!(value, 123);
assert!(!map.contains_key("test_key"));
}
#[test]
fn take_and_parse_key_missing_key() {
let mut map = IndexMap::<String, String>::new();
let result = take_and_parse_key::<i32>(&mut map, "test_key");
assert!(matches!(result, Err(VmfError::InvalidFormat(_))));
if let Err(VmfError::InvalidFormat(msg)) = result {
assert!(msg.contains("'test_key' key not found"));
}
}
#[test]
fn take_and_parse_key_invalid_value() {
let mut map = IndexMap::new();
map.insert("test_key".to_string(), "abc".to_string());
let result = take_and_parse_key::<i32>(&mut map, "test_key");
assert!(matches!(result, Err(VmfError::ParseInt { key, source: _ }) if key == "test_key"));
assert!(!map.contains_key("test_key"));
}
#[test]
fn to_01_string_true() {
assert_eq!(true.to_01_string(), "1");
}
#[test]
fn to_01_string_false() {
assert_eq!(false.to_01_string(), "0");
}
}