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 lua.load(rockspec_content).exec()?;
38
39 let globals = lua.globals();
40
41 if globals.contains_key("version")? {
42 return Err(mlua::Error::custom(
43 "field `version` should not be declared in extra.rockspec.",
44 ));
45 }
46 if globals.contains_key("source")? {
47 return Err(mlua::Error::custom(
48 "field `source` should not be declared in extra.rockspec.",
49 ));
50 }
51
52 let rockspec = PartialLuaRockspec {
53 rockspec_format: globals.get("rockspec_format").unwrap_or_default(),
54 package: globals.get("package").unwrap_or_default(),
55 description: parse_lua_tbl_or_default(&lua, "description").unwrap_or_default(),
56 supported_platforms: parse_lua_tbl_or_default(&lua, "supported_platforms")
57 .unwrap_or_default(),
58 dependencies: lua
59 .from_value(globals.get("dependencies").unwrap_or(Value::Nil))
60 .unwrap_or_default(),
61 build_dependencies: lua
62 .from_value(globals.get("build_dependencies").unwrap_or(Value::Nil))
63 .unwrap_or_default(),
64 test_dependencies: lua
65 .from_value(globals.get("test_dependencies").unwrap_or(Value::Nil))
66 .unwrap_or_default(),
67 external_dependencies: lua
68 .from_value(globals.get("external_dependencies").unwrap_or(Value::Nil))
69 .unwrap_or_default(),
70 build: lua
71 .from_value(globals.get("build").unwrap_or(Value::Nil))
72 .unwrap_or_default(),
73 test: lua
74 .from_value(globals.get("test").unwrap_or(Value::Nil))
75 .unwrap_or_default(),
76 deploy: lua
77 .from_value(globals.get("deploy").unwrap_or(Value::Nil))
78 .unwrap_or_default(),
79 };
80
81 Ok(rockspec)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn parse_partial_rockspec() {
91 let partial_rockspec = r#"
92 package = "my-package"
93 "#;
94
95 PartialLuaRockspec::new(partial_rockspec).unwrap();
96
97 let full_rockspec = r#"
99 rockspec_format = "3.0"
100 package = "my-package"
101
102 description = {
103 summary = "A summary",
104 detailed = "A detailed description",
105 license = "MIT",
106 homepage = "https://example.com",
107 issues_url = "https://example.com/issues",
108 maintainer = "John Doe",
109 labels = {"label1", "label2"},
110 }
111
112 supported_platforms = {"linux", "!windows"}
113
114 dependencies = {
115 "lua 5.1",
116 "foo 1.0",
117 "bar >=2.0",
118 }
119
120 build_dependencies = {
121 "baz 1.0",
122 }
123
124 external_dependencies = {
125 foo = { header = "foo.h" },
126 bar = { library = "libbar.so" },
127 }
128
129 test_dependencies = {
130 "busted 1.0",
131 }
132
133 test = {
134 type = "command",
135 script = "test.lua",
136 flags = {"foo", "bar"},
137 }
138
139 build = {
140 type = "builtin",
141 }
142 "#;
143
144 let rockspec = PartialLuaRockspec::new(full_rockspec).unwrap();
145
146 assert!(rockspec.rockspec_format.is_some());
150 assert!(rockspec.package.is_some());
151 assert!(rockspec.description.is_some());
152 assert!(rockspec.supported_platforms.is_some());
153 assert!(rockspec.dependencies.is_some());
154 assert!(rockspec.build_dependencies.is_some());
155 assert!(rockspec.external_dependencies.is_some());
156 assert!(rockspec.test_dependencies.is_some());
157 assert!(rockspec.build.is_some());
158 assert!(rockspec.test.is_some());
159
160 let partial_rockspec = r#"
162 version = "2.0.0"
163 "#;
164
165 PartialLuaRockspec::new(partial_rockspec).unwrap_err();
166
167 let partial_rockspec = r#"
168 source = {
169 url = "https://example.com",
170 }
171 "#;
172
173 PartialLuaRockspec::new(partial_rockspec).unwrap_err();
174 }
175}