Skip to main content

zoi_lua/
parser.rs

1use crate::functions;
2use anyhow::{Result, anyhow};
3use mlua::{self, Lua, LuaSerdeExt, Table, Value};
4use std::fs;
5use zoi_core::{types, utils};
6
7pub fn parse_lua_package_for_platform(
8    file_path: &str,
9    platform: &str,
10    version_override: Option<&str>,
11    quiet: bool,
12) -> Result<types::Package> {
13    let lua_code = fs::read_to_string(file_path)?;
14    let lua = Lua::new();
15
16    let pkg_meta_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
17    let pkg_deps_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
18    let pkg_updates_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
19    let pkg_hooks_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
20    let pkg_service_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
21    lua.globals()
22        .set("__ZoiPackageMeta", pkg_meta_table)
23        .map_err(|e| anyhow!(e.to_string()))?;
24    lua.globals()
25        .set("__ZoiPackageDeps", pkg_deps_table)
26        .map_err(|e| anyhow!(e.to_string()))?;
27    lua.globals()
28        .set("__ZoiPackageUpdates", pkg_updates_table)
29        .map_err(|e| anyhow!(e.to_string()))?;
30    lua.globals()
31        .set("__ZoiPackageHooks", pkg_hooks_table)
32        .map_err(|e| anyhow!(e.to_string()))?;
33    lua.globals()
34        .set("__ZoiPackageService", pkg_service_table)
35        .map_err(|e| anyhow!(e.to_string()))?;
36
37    let pkg_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
38    lua.globals()
39        .set("PKG", pkg_table)
40        .map_err(|e| anyhow!(e.to_string()))?;
41
42    functions::setup_lua_environment(
43        &lua,
44        platform,
45        version_override,
46        Some(file_path),
47        None,
48        None,
49        None,
50        None,
51        quiet,
52    )
53    .map_err(|e| anyhow!("Failed to setup Lua environment for '{}': {}", file_path, e))?;
54
55    lua.load(&lua_code).exec().map_err(|e| {
56        anyhow!(
57            "Failed to execute Lua package file '{}':
58{}",
59            file_path,
60            e
61        )
62    })?;
63
64    let final_pkg_meta: Table = lua
65        .globals()
66        .get("__ZoiPackageMeta")
67        .map_err(|e| anyhow!(e.to_string()))?;
68    let final_pkg_deps: Table = lua
69        .globals()
70        .get("__ZoiPackageDeps")
71        .map_err(|e| anyhow!(e.to_string()))?;
72    let final_pkg_updates: Table = lua
73        .globals()
74        .get("__ZoiPackageUpdates")
75        .map_err(|e| anyhow!(e.to_string()))?;
76    let final_pkg_hooks: Table = lua
77        .globals()
78        .get("__ZoiPackageHooks")
79        .map_err(|e| anyhow!(e.to_string()))?;
80    let final_pkg_service: Table = lua
81        .globals()
82        .get("__ZoiPackageService")
83        .map_err(|e| anyhow!(e.to_string()))?;
84
85    let mut package: types::Package =
86        lua.from_value(Value::Table(final_pkg_meta)).map_err(|e| {
87            anyhow!(
88                "Failed to parse 'metadata' block in package file '{}':
89{}",
90                file_path,
91                e
92            )
93        })?;
94
95    package.dependencies = if final_pkg_deps.is_empty() {
96        None
97    } else {
98        Some(lua.from_value(Value::Table(final_pkg_deps)).map_err(|e| {
99            anyhow!(
100                "Failed to parse 'dependencies' block in package file '{}':
101{}",
102                file_path,
103                e
104            )
105        })?)
106    };
107
108    package.updates = if final_pkg_updates.is_empty() {
109        None
110    } else {
111        Some(
112            lua.from_value(Value::Table(final_pkg_updates))
113                .map_err(|e| {
114                    anyhow!(
115                        "Failed to parse 'updates' block in package file '{}':
116{}",
117                        file_path,
118                        e
119                    )
120                })?,
121        )
122    };
123
124    package.hooks = if final_pkg_hooks.is_empty() {
125        None
126    } else {
127        Some(lua.from_value(Value::Table(final_pkg_hooks)).map_err(|e| {
128            anyhow!(
129                "Failed to parse 'hooks' block in package file '{}':
130{}",
131                file_path,
132                e
133            )
134        })?)
135    };
136
137    package.service = if final_pkg_service.is_empty() {
138        None
139    } else {
140        Some(
141            lua.from_value(Value::Table(final_pkg_service))
142                .map_err(|e| {
143                    anyhow!(
144                        "Failed to parse 'service' block in package file '{}':
145{}",
146                        file_path,
147                        e
148                    )
149                })?,
150        )
151    };
152
153    Ok(package)
154}
155
156pub fn parse_lua_package(
157    file_path: &str,
158    version_override: Option<&str>,
159    quiet: bool,
160) -> Result<types::Package> {
161    let platform = utils::get_platform()?;
162    parse_lua_package_for_platform(file_path, &platform, version_override, quiet)
163}