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