Add things for sol migration

Co-authored-by: Nerixyz <nerixdev@outlook.de>
This commit is contained in:
Mm2PL 2024-10-03 16:24:42 +02:00
parent a0b434309a
commit 944e447886
No known key found for this signature in database
GPG key ID: 94AC9B80EFA15ED9
4 changed files with 179 additions and 4 deletions

View file

@ -235,14 +235,16 @@ set(SOURCE_FILES
controllers/plugins/api/HTTPResponse.hpp
controllers/plugins/LuaAPI.cpp
controllers/plugins/LuaAPI.hpp
controllers/plugins/PluginPermission.cpp
controllers/plugins/PluginPermission.hpp
controllers/plugins/LuaUtilities.cpp
controllers/plugins/LuaUtilities.hpp
controllers/plugins/Plugin.cpp
controllers/plugins/Plugin.hpp
controllers/plugins/PluginController.hpp
controllers/plugins/PluginController.cpp
controllers/plugins/LuaUtilities.cpp
controllers/plugins/LuaUtilities.hpp
controllers/plugins/PluginPermission.cpp
controllers/plugins/PluginPermission.hpp
controllers/plugins/SolTypes.cpp
controllers/plugins/SolTypes.hpp
controllers/sound/ISoundController.hpp
controllers/sound/MiniaudioBackend.cpp

View file

@ -129,6 +129,10 @@
# include <unordered_set>
# include <vector>
# ifdef CHATTERINO_HAVE_PLUGINS
# include <sol/sol.hpp>
# endif
# ifndef UNUSED
# define UNUSED(x) (void)(x)
# endif

View file

@ -0,0 +1,58 @@
#ifdef CHATTERINO_HAVE_PLUGINS
# include "controllers/plugins/SolTypes.hpp"
// NOLINTBEGIN(readability-named-parameter)
// QString
bool sol_lua_check(sol::types<QString>, lua_State *L, int index,
std::function<sol::check_handler_type> handler,
sol::stack::record &tracking)
{
return sol::stack::check<const char *>(L, index, handler, tracking);
}
QString sol_lua_get(sol::types<QString>, lua_State *L, int index,
sol::stack::record &tracking)
{
auto str = sol::stack::get<std::string_view>(L, index, tracking);
return QString::fromUtf8(str.data(), static_cast<qsizetype>(str.length()));
}
int sol_lua_push(sol::types<QString>, lua_State *L, const QString &value)
{
return sol::stack::push(L, value.toUtf8().data());
}
// QStringList
bool sol_lua_check(sol::types<QStringList>, lua_State *L, int index,
std::function<sol::check_handler_type> handler,
sol::stack::record &tracking)
{
return sol::stack::check<sol::table>(L, index, handler, tracking);
}
QStringList sol_lua_get(sol::types<QStringList>, lua_State *L, int index,
sol::stack::record &tracking)
{
sol::table table = sol::stack::get<sol::table>(L, index, tracking);
QStringList result;
result.reserve(static_cast<qsizetype>(table.size()));
for (size_t i = 1; i < table.size() + 1; i++)
{
result.append(table.get<QString>(i));
}
return result;
}
int sol_lua_push(sol::types<QStringList>, lua_State *L,
const QStringList &value)
{
sol::table table = sol::table::create(L, static_cast<int>(value.size()));
for (const QString &str : value)
{
table.add(str);
}
return sol::stack::push(L, table);
}
// NOLINTEND(readability-named-parameter)
#endif

View file

@ -0,0 +1,111 @@
#pragma once
#ifdef CHATTERINO_HAVE_PLUGINS
# include "util/QMagicEnum.hpp"
# include "util/TypeName.hpp"
# include <nonstd/expected.hpp>
# include <QString>
# include <QStringBuilder>
# include <QStringList>
# include <sol/sol.hpp>
namespace chatterino::detail {
// NOLINTBEGIN(readability-identifier-naming)
template <typename T>
constexpr bool IsOptional = false;
template <typename T>
constexpr bool IsOptional<std::optional<T>> = true;
// NOLINTEND(readability-identifier-naming)
} // namespace chatterino::detail
namespace chatterino::lua {
/// @brief Attempts to call @a function with @a args
///
/// @a T is expected to be returned.
/// If `void` is specified, the returned values
/// are ignored.
/// `std::optional` signifies zero or one returned values.
template <typename T, typename... Args>
inline nonstd::expected_lite::expected<T, QString> tryCall(
const sol::protected_function &function, Args &&...args)
{
sol::protected_function_result result =
function(std::forward<Args>(args)...);
if (!result.valid())
{
sol::error err = result;
return nonstd::expected_lite::make_unexpected(
QString::fromUtf8(err.what()));
}
if constexpr (std::is_same_v<T, void>)
{
return {};
}
if constexpr (detail::IsOptional<T>)
{
if (result.return_count() == 0)
{
return {};
}
}
if (result.return_count() > 1)
{
return nonstd::expected_lite::make_unexpected(
u"Expected one value to be returned but " %
QString::number(result.return_count()) % u" values were returned");
}
try
{
// XXX: this has weird failure modes,
// std::optional<T> means this is fallible, but we want nil|LuaFor<T>
if constexpr (detail::IsOptional<T>)
{
return result.get<T>();
}
else
{
auto ret = result.get<std::optional<T>>();
if (!ret)
{
auto t = type_name<T>();
return nonstd::expected_lite::make_unexpected(
u"Expected " % QLatin1String(t.data(), t.size()) %
u" to be returned but " %
qmagicenum::enumName(result.get_type()) % u" was returned");
}
return *ret;
}
}
catch (std::runtime_error &e)
{
return nonstd::expected_lite::make_unexpected(
QString::fromUtf8(e.what()));
}
// non other exceptions we let it explode
}
} // namespace chatterino::lua
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
# define SOL_STACK_FUNCTIONS(TYPE) \
bool sol_lua_check(sol::types<TYPE>, lua_State *L, int index, \
std::function<sol::check_handler_type> handler, \
sol::stack::record &tracking); \
TYPE sol_lua_get(sol::types<TYPE>, lua_State *L, int index, \
sol::stack::record &tracking); \
int sol_lua_push(sol::types<TYPE>, lua_State *L, const TYPE &value);
SOL_STACK_FUNCTIONS(QString)
SOL_STACK_FUNCTIONS(QStringList)
# undef SOL_STACK_FUNCTIONS
#endif