lux_lib/lua_rockspec/
partial.rs1use std::collections::HashMap;
2
3use mlua::{Lua, LuaSerdeExt, UserData, Value};
4use serde::de::Error;
5
6use crate::{
7 lua_rockspec::RockspecFormat, package::PackageName, rockspec::lua_dependency::LuaDependencySpec,
8};
9
10use super::{
11 parse_lua_tbl_or_default, BuildSpecInternal, DeploySpec, ExternalDependencySpec,
12 PlatformSupport, RockDescription, TestSpecInternal,
13};
14
15#[derive(Debug)]
16pub struct PartialLuaRockspec {
17 pub(crate) rockspec_format: Option<RockspecFormat>,
18 pub(crate) package: Option<PackageName>,
19 pub(crate) build: Option<BuildSpecInternal>,
20 pub(crate) deploy: Option<DeploySpec>,
21 pub(crate) description: Option<RockDescription>,
22 pub(crate) supported_platforms: Option<PlatformSupport>,
23 pub(crate) dependencies: Option<Vec<LuaDependencySpec>>,
24 pub(crate) build_dependencies: Option<Vec<LuaDependencySpec>>,
25 pub(crate) external_dependencies: Option<HashMap<String, ExternalDependencySpec>>,
26 pub(crate) test_dependencies: Option<Vec<LuaDependencySpec>>,
27 pub(crate) test: Option<TestSpecInternal>,
28}
29
30impl UserData for PartialLuaRockspec {}
31
32pub type PartialRockspecError = mlua::Error;
33
34impl PartialLuaRockspec {
35 pub fn new(rockspec_content: &str) -> Result<Self, PartialRockspecError> {
36 let lua = Lua::new();
37
38 #[cfg(feature = "luau")]
39 lua.sandbox(true)?;
40
41 lua.load(rockspec_content).exec()?;
42
43 let globals = lua.globals();
44
45 if globals.contains_key("version")? {
46 return Err(mlua::Error::custom(
47 "field `version` should not be declared in extra.rockspec.",
48 ));
49 }
50 if globals.contains_key("source")? {
51 return Err(mlua::Error::custom(
52 "field `source` should not be declared in extra.rockspec.",
53 ));
54 }
55
56 let rockspec = PartialLuaRockspec {
57 rockspec_format: globals.get("rockspec_format").unwrap_or_default(),
58 package: globals.get("package").unwrap_or_default(),
59 description: parse_lua_tbl_or_default(&lua, "description").unwrap_or_default(),
60 supported_platforms: parse_lua_tbl_or_default(&lua, "supported_platforms")
61 .unwrap_or_default(),
62 dependencies: lua
63 .from_value(globals.get("dependencies").unwrap_or(Value::Nil))
64 .unwrap_or_default(),
65 build_dependencies: lua
66 .from_value(globals.get("build_dependencies").unwrap_or(Value::Nil))
67 .unwrap_or_default(),
68 test_dependencies: lua
69 .from_value(globals.get("test_dependencies").unwrap_or(Value::Nil))
70 .unwrap_or_default(),
71 external_dependencies: lua
72 .from_value(globals.get("external_dependencies").unwrap_or(Value::Nil))
73 .unwrap_or_default(),
74 build: lua
75 .from_value(globals.get("build").unwrap_or(Value::Nil))
76 .unwrap_or_default(),
77 test: lua
78 .from_value(globals.get("test").unwrap_or(Value::Nil))
79 .unwrap_or_default(),
80 deploy: lua
81 .from_value(globals.get("deploy").unwrap_or(Value::Nil))
82 .unwrap_or_default(),
83 };
84
85 Ok(rockspec)
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn parse_partial_rockspec() {
95 let partial_rockspec = r#"
96 package = "my-package"
97 "#;
98
99 PartialLuaRockspec::new(partial_rockspec).unwrap();
100
101 let full_rockspec = r#"
103 rockspec_format = "3.0"
104 package = "my-package"
105
106 description = {
107 summary = "A summary",
108 detailed = "A detailed description",
109 license = "MIT",
110 homepage = "https://example.com",
111 issues_url = "https://example.com/issues",
112 maintainer = "John Doe",
113 labels = {"label1", "label2"},
114 }
115
116 supported_platforms = {"linux", "!windows"}
117
118 dependencies = {
119 "lua 5.1",
120 "foo 1.0",
121 "bar >=2.0",
122 }
123
124 build_dependencies = {
125 "baz 1.0",
126 }
127
128 external_dependencies = {
129 foo = { header = "foo.h" },
130 bar = { library = "libbar.so" },
131 }
132
133 test_dependencies = {
134 "busted 1.0",
135 }
136
137 test = {
138 type = "command",
139 script = "test.lua",
140 flags = {"foo", "bar"},
141 }
142
143 build = {
144 type = "builtin",
145 }
146 "#;
147
148 let rockspec = PartialLuaRockspec::new(full_rockspec).unwrap();
149
150 assert!(rockspec.rockspec_format.is_some());
154 assert!(rockspec.package.is_some());
155 assert!(rockspec.description.is_some());
156 assert!(rockspec.supported_platforms.is_some());
157 assert!(rockspec.dependencies.is_some());
158 assert!(rockspec.build_dependencies.is_some());
159 assert!(rockspec.external_dependencies.is_some());
160 assert!(rockspec.test_dependencies.is_some());
161 assert!(rockspec.build.is_some());
162 assert!(rockspec.test.is_some());
163
164 let partial_rockspec = r#"
166 version = "2.0.0"
167 "#;
168
169 PartialLuaRockspec::new(partial_rockspec).unwrap_err();
170
171 let partial_rockspec = r#"
172 source = {
173 url = "https://example.com",
174 }
175 "#;
176
177 PartialLuaRockspec::new(partial_rockspec).unwrap_err();
178 }
179}