use crate::Error;
use crate::dir_context::PathResolver;
use crate::runtime::Runtime;
use crate::script::serde_value_to_lua_value;
use crate::support::tomls;
use mlua::{Lua, Value};
use simple_fs::read_to_string;
pub(super) fn file_load_toml(lua: &Lua, runtime: &Runtime, path: String) -> mlua::Result<Value> {
let full_path =
runtime
.dir_context()
.resolve_path(runtime.session(), path.clone().into(), PathResolver::WksDir, None)?;
let content = read_to_string(&full_path).map_err(|e| {
Error::from(format!(
"aip.file.load_toml - Failed to read toml file '{path}'.\nCause: {e}",
))
})?;
let toml_value = tomls::parse_toml_into_json(&content).map_err(|e| {
Error::from(format!(
"aip.file.load_toml - Failed to parse toml file '{path}'.\nCause: {e}",
))
})?;
let lua_value = serde_value_to_lua_value(lua, toml_value)?;
Ok(lua_value)
}
#[cfg(test)]
mod tests {
type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
use crate::_test_support::{
assert_contains, clean_sanbox_01_tmp_file, create_sanbox_01_tmp_file, run_reflective_agent,
};
use value_ext::JsonValueExt as _;
#[tokio::test]
async fn test_lua_file_load_toml_ok() -> Result<()> {
let fx_file = create_sanbox_01_tmp_file(
"test_lua_file_load_toml_ok.toml",
r#"
title = "Test TOML"
enabled = true
values = [1, 2, 3]
[owner]
name = "Owner Name"
tags = ["alpha", "beta"]
[[servers]]
name = "alpha"
port = 8080
[[servers]]
name = "beta"
port = 9090
"#,
)?;
let fx_path = fx_file.as_str();
let res = run_reflective_agent(&format!(r#"return aip.file.load_toml("{fx_path}")"#), None).await?;
assert_eq!(res.x_get_str("title")?, "Test TOML");
assert!(res.x_get_bool("enabled")?);
let values = res
.get("values")
.ok_or("should have values")?
.as_array()
.ok_or("values should be array")?;
assert_eq!(values.len(), 3);
assert_eq!(values[0].as_i64().ok_or("should have i64")?, 1);
let owner = res.get("owner").ok_or("should have owner")?;
assert_eq!(owner.x_get_str("name")?, "Owner Name");
let tags = owner
.get("tags")
.ok_or("owner should have tags")?
.as_array()
.ok_or("tags should be array")?;
assert_eq!(tags[0].as_str().ok_or("tag should be string")?, "alpha");
let servers = res
.get("servers")
.ok_or("should have servers")?
.as_array()
.ok_or("servers should be array")?;
assert_eq!(servers.len(), 2);
assert_eq!(servers[1].x_get_str("name")?, "beta");
assert_eq!(servers[1].x_get_i64("port")?, 9090);
Ok(())
}
#[tokio::test]
async fn test_lua_file_load_toml_file_not_found() -> Result<()> {
let fx_path = "other/non_existent_file.toml";
let res = run_reflective_agent(&format!(r#"return aip.file.load_toml("{fx_path}")"#), None).await;
let Err(err) = res else {
panic!("Should have returned an error");
};
assert_contains(&err.to_string(), "aip.file.load_toml - Failed to read toml file");
assert_contains(&err.to_string(), "non_existent_file.toml");
Ok(())
}
#[tokio::test]
async fn test_lua_file_load_toml_invalid_toml() -> Result<()> {
let fx_file = create_sanbox_01_tmp_file(
"test_lua_file_load_toml_invalid.toml",
r#"
title = "Test
"#,
)?;
let fx_path = fx_file.as_str();
let res = run_reflective_agent(&format!(r#"return aip.file.load_toml("{fx_path}")"#), None).await;
let Err(err) = res else {
panic!("Should have returned an error");
};
assert_contains(&err.to_string(), "aip.file.load_toml - Failed to parse toml file");
assert_contains(&err.to_string(), fx_path);
clean_sanbox_01_tmp_file(fx_file)?;
Ok(())
}
}