1use anyhow::Context;
2use config::{
3 any_err, get_or_create_module, get_or_create_sub_module, materialize_to_lua_value,
4 serialize_options,
5};
6use mlua::{Lua, LuaSerdeExt, Value as LuaValue};
7use serde_json::Value as JValue;
8
9pub fn register(lua: &Lua) -> anyhow::Result<()> {
10 let serde_mod = get_or_create_sub_module(lua, "serde")?;
11 let kumo_mod = get_or_create_module(lua, "kumo")?;
12
13 serde_mod.set("json_load", lua.create_async_function(json_load)?)?;
14 serde_mod.set("json_parse", lua.create_function(json_parse)?)?;
15 serde_mod.set("json_encode", lua.create_function(json_encode)?)?;
16 serde_mod.set(
17 "json_encode_pretty",
18 lua.create_function(json_encode_pretty)?,
19 )?;
20
21 serde_mod.set("toml_load", lua.create_async_function(toml_load)?)?;
22 serde_mod.set("toml_parse", lua.create_function(toml_parse)?)?;
23 serde_mod.set("toml_encode", lua.create_function(toml_encode)?)?;
24 serde_mod.set(
25 "toml_encode_pretty",
26 lua.create_function(toml_encode_pretty)?,
27 )?;
28
29 serde_mod.set("yaml_load", lua.create_async_function(yaml_load)?)?;
30 serde_mod.set("yaml_parse", lua.create_function(yaml_parse)?)?;
31 serde_mod.set("yaml_encode", lua.create_function(yaml_encode)?)?;
32 kumo_mod.set("json_load", lua.create_async_function(json_load)?)?;
37 kumo_mod.set("json_parse", lua.create_function(json_parse)?)?;
38 kumo_mod.set("json_encode", lua.create_function(json_encode)?)?;
39 kumo_mod.set(
40 "json_encode_pretty",
41 lua.create_function(json_encode_pretty)?,
42 )?;
43
44 kumo_mod.set("toml_load", lua.create_async_function(toml_load)?)?;
45 kumo_mod.set("toml_parse", lua.create_function(toml_parse)?)?;
46 kumo_mod.set("toml_encode", lua.create_function(toml_encode)?)?;
47 kumo_mod.set(
48 "toml_encode_pretty",
49 lua.create_function(toml_encode_pretty)?,
50 )?;
51
52 Ok(())
53}
54
55async fn json_load(lua: Lua, file_name: String) -> mlua::Result<LuaValue> {
56 let data = tokio::fs::read(&file_name)
57 .await
58 .with_context(|| format!("reading file {file_name}"))
59 .map_err(any_err)?;
60
61 let stripped = json_comments::StripComments::new(&*data);
62
63 let obj: serde_json::Value = serde_json::from_reader(stripped)
64 .with_context(|| format!("parsing {file_name} as json"))
65 .map_err(any_err)?;
66 lua.to_value_with(&obj, serialize_options())
67}
68
69fn json_parse(lua: &Lua, text: String) -> mlua::Result<LuaValue> {
70 let stripped = json_comments::StripComments::new(text.as_bytes());
71 let obj: serde_json::Value = serde_json::from_reader(stripped)
72 .with_context(|| format!("parsing {text} as json"))
73 .map_err(any_err)?;
74 lua.to_value_with(&obj, serialize_options())
75}
76
77fn json_encode(lua: &Lua, value: LuaValue) -> mlua::Result<String> {
78 let value = materialize_to_lua_value(lua, value)?;
79 serde_json::to_string(&value).map_err(any_err)
80}
81
82fn json_encode_pretty(lua: &Lua, value: LuaValue) -> mlua::Result<String> {
83 let value = materialize_to_lua_value(lua, value)?;
84 serde_json::to_string_pretty(&value).map_err(any_err)
85}
86
87async fn toml_load(lua: Lua, file_name: String) -> mlua::Result<LuaValue> {
88 let data = tokio::fs::read_to_string(&file_name)
89 .await
90 .with_context(|| format!("reading file {file_name}"))
91 .map_err(any_err)?;
92
93 let obj: toml::Value = toml::from_str(&data)
94 .with_context(|| format!("parsing {file_name} as toml"))
95 .map_err(any_err)?;
96 lua.to_value_with(&obj, serialize_options())
97}
98
99fn toml_parse(lua: &Lua, toml: String) -> mlua::Result<LuaValue> {
100 let obj: toml::Value = toml::from_str(&toml)
101 .with_context(|| format!("parsing {toml} as toml"))
102 .map_err(any_err)?;
103 lua.to_value_with(&obj, serialize_options())
104}
105
106fn toml_encode(lua: &Lua, value: LuaValue) -> mlua::Result<String> {
107 let value = materialize_to_lua_value(lua, value)?;
108 toml::to_string(&value).map_err(any_err)
109}
110
111fn toml_encode_pretty(lua: &Lua, value: LuaValue) -> mlua::Result<String> {
112 let value = materialize_to_lua_value(lua, value)?;
113 toml::to_string_pretty(&value).map_err(any_err)
114}
115
116async fn yaml_load(lua: Lua, file_name: String) -> mlua::Result<LuaValue> {
117 let data = tokio::fs::read(&file_name)
118 .await
119 .with_context(|| format!("reading file {file_name}"))
120 .map_err(any_err)?;
121
122 let value: JValue = serde_yaml::from_slice(&data)
123 .with_context(|| format!("parsing {file_name} as yaml"))
124 .map_err(any_err)?;
125 lua.to_value_with(&value, serialize_options())
126}
127
128fn yaml_parse(lua: &Lua, text: String) -> mlua::Result<LuaValue> {
129 let value: JValue = serde_yaml::from_str(&text)
130 .with_context(|| format!("parsing {text} as yaml"))
131 .map_err(any_err)?;
132 lua.to_value_with(&value, serialize_options())
133}
134
135fn yaml_encode(lua: &Lua, value: LuaValue) -> mlua::Result<String> {
136 let value = materialize_to_lua_value(lua, value)?;
137 serde_yaml::to_string(&value).map_err(any_err)
138}