1use std::{
2 collections::HashMap,
3 fmt::Display,
4 ops::{Deref, DerefMut},
5 path::PathBuf,
6};
7
8use itertools::Itertools;
9use lua_dependency::LuaDependencySpec;
10use mlua::IntoLua;
11use serde::{Deserialize, Serialize};
12pub mod lua_dependency;
13
14use crate::{
15 config::{Config, LuaVersion},
16 lua_rockspec::{
17 BuildSpec, DeploySpec, ExternalDependencySpec, LuaVersionError, PerPlatform,
18 PlatformSupport, RemoteRockSource, RockDescription, RockspecFormat, TestSpec,
19 },
20 package::{PackageName, PackageVersion, PackageVersionReq},
21};
22
23pub trait Rockspec {
24 type Error: Display + std::fmt::Debug;
25
26 fn package(&self) -> &PackageName;
27 fn version(&self) -> &PackageVersion;
28 fn description(&self) -> &RockDescription;
29 fn supported_platforms(&self) -> &PlatformSupport;
30 fn lua(&self) -> &PackageVersionReq;
31 fn dependencies(&self) -> &PerPlatform<Vec<LuaDependencySpec>>;
32 fn build_dependencies(&self) -> &PerPlatform<Vec<LuaDependencySpec>>;
33 fn external_dependencies(&self) -> &PerPlatform<HashMap<String, ExternalDependencySpec>>;
34 fn test_dependencies(&self) -> &PerPlatform<Vec<LuaDependencySpec>>;
35
36 fn build(&self) -> &PerPlatform<BuildSpec>;
37 fn test(&self) -> &PerPlatform<TestSpec>;
38 fn source(&self) -> &PerPlatform<RemoteRockSource>;
39 fn deploy(&self) -> &PerPlatform<DeploySpec>;
40
41 fn build_mut(&mut self) -> &mut PerPlatform<BuildSpec>;
42 fn test_mut(&mut self) -> &mut PerPlatform<TestSpec>;
43 fn source_mut(&mut self) -> &mut PerPlatform<RemoteRockSource>;
44 fn deploy_mut(&mut self) -> &mut PerPlatform<DeploySpec>;
45
46 fn format(&self) -> &Option<RockspecFormat>;
47
48 fn binaries(&self) -> RockBinaries {
50 RockBinaries(
51 self.build()
52 .current_platform()
53 .install
54 .bin
55 .keys()
56 .map_into()
57 .collect(),
58 )
59 }
60
61 fn to_lua_remote_rockspec_string(&self) -> Result<String, Self::Error>;
63}
64
65pub trait LuaVersionCompatibility {
66 fn validate_lua_version(&self, config: &Config) -> Result<(), LuaVersionError>;
69
70 fn lua_version_matches(&self, config: &Config) -> Result<LuaVersion, LuaVersionError>;
73
74 fn supports_lua_version(&self, lua_version: &LuaVersion) -> bool;
76
77 fn lua_version(&self) -> Option<LuaVersion>;
79}
80
81impl<T: Rockspec> LuaVersionCompatibility for T {
82 fn validate_lua_version(&self, config: &Config) -> Result<(), LuaVersionError> {
83 let _ = self.lua_version_matches(config)?;
84 Ok(())
85 }
86
87 fn lua_version_matches(&self, config: &Config) -> Result<LuaVersion, LuaVersionError> {
88 let version = LuaVersion::from(config)?.clone();
89 if self.supports_lua_version(&version) {
90 Ok(version)
91 } else {
92 Err(LuaVersionError::LuaVersionUnsupported(
93 version,
94 self.package().to_owned(),
95 self.version().to_owned(),
96 ))
97 }
98 }
99
100 fn supports_lua_version(&self, lua_version: &LuaVersion) -> bool {
101 self.lua().matches(&lua_version.as_version())
102 }
103
104 fn lua_version(&self) -> Option<LuaVersion> {
105 for (possibility, version) in [
106 ("5.4.0", LuaVersion::Lua54),
107 ("5.3.0", LuaVersion::Lua53),
108 ("5.2.0", LuaVersion::Lua52),
109 ("5.1.0", LuaVersion::Lua51),
110 ] {
111 if self.lua().matches(&possibility.parse().unwrap()) {
112 return Some(version);
113 }
114 }
115 None
116 }
117}
118
119#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialOrd, Ord, Hash, PartialEq, Eq)]
120pub struct RockBinaries(Vec<PathBuf>);
121
122impl Deref for RockBinaries {
123 type Target = Vec<PathBuf>;
124
125 fn deref(&self) -> &Self::Target {
126 &self.0
127 }
128}
129
130impl DerefMut for RockBinaries {
131 fn deref_mut(&mut self) -> &mut Self::Target {
132 &mut self.0
133 }
134}
135
136impl IntoLua for RockBinaries {
137 fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
138 self.0.into_lua(lua)
139 }
140}