use std::collections::HashMap;
use emmylua_parser::{LuaFeatures, LuaLanguageLevel, LuaVersionNumber, SpecialFunction};
use schemars::JsonSchema;
use serde::de::Deserializer;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)]
#[serde(rename_all = "camelCase")]
#[derive(Default)]
pub struct EmmyrcRuntime {
#[serde(default)]
pub version: EmmyrcLuaVersion,
#[serde(default)]
pub require_like_function: Vec<String>,
#[serde(default)]
pub framework_versions: Vec<String>,
#[serde(default)]
pub extensions: Vec<String>,
#[serde(default)]
pub require_pattern: Vec<String>,
#[serde(default)]
pub nonstandard_symbol: Vec<EmmyrcNonStdSymbol>,
#[serde(default)]
pub special: HashMap<String, EmmyrcSpecialSymbol>,
}
#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone, Copy, PartialEq, Eq, Default)]
pub enum EmmyrcLuaVersion {
#[serde(rename = "Lua5.1", alias = "Lua 5.1")]
Lua51,
#[serde(rename = "LuaJIT")]
LuaJIT,
#[serde(rename = "LuaJIT-Ext", alias = "LuaJIT Ext")]
LuaJITExt,
#[serde(rename = "LuaJIT3", alias = "LuaJIT 3")]
LuaJIT3,
#[serde(rename = "Lua5.2", alias = "Lua 5.2")]
Lua52,
#[serde(rename = "Lua5.3", alias = "Lua 5.3")]
Lua53,
#[serde(rename = "Lua5.4", alias = "Lua 5.4")]
Lua54,
#[serde(rename = "Lua5.5", alias = "Lua 5.5")]
Lua55,
#[serde(rename = "LuaLatest", alias = "Lua Latest")]
#[default]
LuaLatest,
}
impl EmmyrcLuaVersion {
pub fn to_lua_version_number(&self) -> LuaVersionNumber {
match self {
EmmyrcLuaVersion::Lua51 => LuaVersionNumber::new(5, 1, 0),
EmmyrcLuaVersion::LuaJIT => LuaVersionNumber::LUA_JIT,
EmmyrcLuaVersion::LuaJITExt => LuaVersionNumber::LUA_JIT,
EmmyrcLuaVersion::LuaJIT3 => LuaVersionNumber::LUA_JIT,
EmmyrcLuaVersion::Lua52 => LuaVersionNumber::new(5, 2, 0),
EmmyrcLuaVersion::Lua53 => LuaVersionNumber::new(5, 3, 0),
EmmyrcLuaVersion::Lua54 => LuaVersionNumber::new(5, 4, 0),
EmmyrcLuaVersion::LuaLatest => LuaVersionNumber::new(5, 4, 0),
EmmyrcLuaVersion::Lua55 => LuaVersionNumber::new(5, 5, 0),
}
}
pub fn get_language_level(&self) -> LuaLanguageLevel {
match self {
EmmyrcLuaVersion::Lua51 => LuaLanguageLevel::Lua51,
EmmyrcLuaVersion::LuaJIT => LuaLanguageLevel::LuaJIT,
EmmyrcLuaVersion::LuaJITExt => LuaLanguageLevel::LuaJITExt,
EmmyrcLuaVersion::LuaJIT3 => LuaLanguageLevel::LuaJIT3,
EmmyrcLuaVersion::Lua52 => LuaLanguageLevel::Lua52,
EmmyrcLuaVersion::Lua53 => LuaLanguageLevel::Lua53,
EmmyrcLuaVersion::Lua54 => LuaLanguageLevel::Lua54,
EmmyrcLuaVersion::LuaLatest => LuaLanguageLevel::Lua55,
EmmyrcLuaVersion::Lua55 => LuaLanguageLevel::Lua55,
}
}
pub fn is_luajit(&self) -> bool {
matches!(
self,
EmmyrcLuaVersion::LuaJIT | EmmyrcLuaVersion::LuaJITExt | EmmyrcLuaVersion::LuaJIT3
)
}
}
#[allow(unused)]
fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub enum EmmyrcNonStdSymbol {
#[serde(rename = "//")]
DoubleSlash = 1, #[serde(rename = "/**/")]
SlashStar, #[serde(rename = "`")]
Backtick, #[serde(rename = "+=")]
PlusAssign, #[serde(rename = "-=")]
MinusAssign, #[serde(rename = "*=")]
StarAssign, #[serde(rename = "/=")]
SlashAssign, #[serde(rename = "%=")]
PercentAssign, #[serde(rename = "^=")]
CaretAssign, #[serde(rename = "//=")]
DoubleSlashAssign, #[serde(rename = "|=")]
PipeAssign, #[serde(rename = "&=")]
AmpAssign, #[serde(rename = "<<=")]
ShiftLeftAssign, #[serde(rename = ">>=")]
ShiftRightAssign, #[serde(rename = "||")]
DoublePipe, #[serde(rename = "&&")]
DoubleAmp, #[serde(rename = "!")]
Exclamation, #[serde(rename = "!=")]
NotEqual, #[serde(rename = "continue")]
Continue, }
impl From<EmmyrcNonStdSymbol> for LuaFeatures {
fn from(symbol: EmmyrcNonStdSymbol) -> Self {
match symbol {
EmmyrcNonStdSymbol::DoubleSlash => LuaFeatures::DoubleSlash,
EmmyrcNonStdSymbol::SlashStar => LuaFeatures::SlashStar,
EmmyrcNonStdSymbol::Backtick => LuaFeatures::StringInterpolation,
EmmyrcNonStdSymbol::PlusAssign => LuaFeatures::PlusAssign,
EmmyrcNonStdSymbol::MinusAssign => LuaFeatures::MinusAssign,
EmmyrcNonStdSymbol::StarAssign => LuaFeatures::StarAssign,
EmmyrcNonStdSymbol::SlashAssign => LuaFeatures::SlashAssign,
EmmyrcNonStdSymbol::PercentAssign => LuaFeatures::PercentAssign,
EmmyrcNonStdSymbol::CaretAssign => LuaFeatures::CaretAssign,
EmmyrcNonStdSymbol::DoubleSlashAssign => LuaFeatures::DoubleSlashAssign,
EmmyrcNonStdSymbol::PipeAssign => LuaFeatures::PipeAssign,
EmmyrcNonStdSymbol::AmpAssign => LuaFeatures::AmpAssign,
EmmyrcNonStdSymbol::ShiftLeftAssign => LuaFeatures::ShiftLeftAssign,
EmmyrcNonStdSymbol::ShiftRightAssign => LuaFeatures::ShiftRightAssign,
EmmyrcNonStdSymbol::DoublePipe => LuaFeatures::DoublePipeOr,
EmmyrcNonStdSymbol::DoubleAmp => LuaFeatures::DoubleAmpAnd,
EmmyrcNonStdSymbol::Exclamation => LuaFeatures::Exclamation,
EmmyrcNonStdSymbol::NotEqual => LuaFeatures::NotEqual,
EmmyrcNonStdSymbol::Continue => LuaFeatures::Continue,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, JsonSchema, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum EmmyrcSpecialSymbol {
#[serde(rename = "none")]
None,
Require,
Error,
Assert,
Type,
Setmetatable,
}
impl<'de> Deserialize<'de> for EmmyrcSpecialSymbol {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
"none" => Ok(EmmyrcSpecialSymbol::None),
"require" => Ok(EmmyrcSpecialSymbol::Require),
"error" => Ok(EmmyrcSpecialSymbol::Error),
"assert" => Ok(EmmyrcSpecialSymbol::Assert),
"type" => Ok(EmmyrcSpecialSymbol::Type),
"setmetatable" => Ok(EmmyrcSpecialSymbol::Setmetatable),
_ => Ok(EmmyrcSpecialSymbol::None),
}
}
}
impl From<EmmyrcSpecialSymbol> for Option<SpecialFunction> {
fn from(symbol: EmmyrcSpecialSymbol) -> Self {
match symbol {
EmmyrcSpecialSymbol::None => None,
EmmyrcSpecialSymbol::Require => Some(SpecialFunction::Require),
EmmyrcSpecialSymbol::Error => Some(SpecialFunction::Error),
EmmyrcSpecialSymbol::Assert => Some(SpecialFunction::Assert),
EmmyrcSpecialSymbol::Type => Some(SpecialFunction::Type),
EmmyrcSpecialSymbol::Setmetatable => Some(SpecialFunction::Setmetaatable),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_emmyrc_runtime() {
let json1 = r#"{
"version": "Lua5.1"
}"#;
let runtime: EmmyrcRuntime = serde_json::from_str(json1).unwrap();
assert_eq!(runtime.version, EmmyrcLuaVersion::Lua51);
let json2 = r#"{
"version": "Lua 5.1"
}"#;
let runtime: EmmyrcRuntime = serde_json::from_str(json2).unwrap();
assert_eq!(runtime.version, EmmyrcLuaVersion::Lua51);
}
}