use crate::runtime::Runtime;
use crate::script::lua_value_to_serde_value;
use crate::support::yamls;
use crate::{Error, Result};
use mlua::{IntoLua, Lua, Table, Value};
pub fn init_module(lua: &Lua, _runtime: &Runtime) -> Result<Table> {
let table = lua.create_table()?;
let parse_fn = lua.create_function(move |lua, content: Option<String>| parse(lua, content))?;
let stringify_fn = lua.create_function(move |lua, content: Value| stringify(lua, content))?;
let stringify_multi_docs_fn = lua.create_function(move |lua, content: Value| stringify_multi_docs(lua, content))?;
table.set("parse", parse_fn)?;
table.set("stringify", stringify_fn)?;
table.set("stringify_multi_docs", stringify_multi_docs_fn)?;
Ok(table)
}
fn parse(lua: &Lua, content: Option<String>) -> mlua::Result<Value> {
let Some(content) = content else {
return Ok(Value::Nil);
};
let yaml_docs = yamls::parse(&content).map_err(|err| Error::custom(format!("aip.yaml.parse failed. {err}")))?;
let lua_value = yaml_docs.into_lua(lua)?;
Ok(lua_value)
}
fn stringify(_lua: &Lua, content: Value) -> mlua::Result<String> {
let json_value = lua_value_to_serde_value(content)?;
yamls::stringify(&json_value)
.map_err(|err| Error::custom(format!("aip.yaml.stringify fail to stringify. {err}")).into())
}
fn stringify_multi_docs(_lua: &Lua, content: Value) -> mlua::Result<String> {
let json_value = lua_value_to_serde_value(content)?;
if let serde_json::Value::Array(values) = json_value {
yamls::stringify_multi(&values)
.map_err(|err| Error::custom(format!("aip.yaml.stringify_multi_docs fail to stringify. {err}")).into())
} else {
Err(Error::custom("aip.yaml.stringify_multi_docs failed. Content must be a list of tables.").into())
}
}
#[cfg(test)]
mod tests {
type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
use crate::_test_support::{assert_contains, eval_lua, setup_lua};
use crate::script::aip_modules;
#[tokio::test]
async fn test_script_lua_yaml_parse_multi() -> Result<()> {
let lua = setup_lua(aip_modules::aip_yaml::init_module, "yaml").await?;
let script = r#"
local content = [[
name: Doc1
---
name: Doc2
]]
return aip.yaml.parse(content)
"#;
let res = eval_lua(&lua, script)?;
assert_eq!(res[0]["name"], "Doc1");
assert_eq!(res[1]["name"], "Doc2");
Ok(())
}
#[tokio::test]
async fn test_script_lua_yaml_stringify_simple() -> Result<()> {
let lua = setup_lua(aip_modules::aip_yaml::init_module, "yaml").await?;
let script = r#"
local obj = { name = "John", age = 30 }
return aip.yaml.stringify(obj)
"#;
let res = eval_lua(&lua, script)?;
let s = res.as_str().ok_or("Should have res")?;
assert_contains(s, "name: John");
assert_contains(s, "age: 30");
Ok(())
}
#[tokio::test]
async fn test_script_lua_yaml_stringify_multi() -> Result<()> {
let lua = setup_lua(aip_modules::aip_yaml::init_module, "yaml").await?;
let script = r#"
local docs = { {name = "D1"}, {name = "D2"} }
return aip.yaml.stringify_multi_docs(docs)
"#;
let res = eval_lua(&lua, script)?;
let s = res.as_str().ok_or("Should have res")?;
assert_contains(s, "name: D1");
assert_contains(s, "---");
assert_contains(s, "name: D2");
Ok(())
}
}