You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

132 lines
4.6 KiB

#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <sol/sol.hpp>
#include "utils/str_cat.hpp"
namespace devilution {
enum class LuaUserdataMemberType : uint8_t {
ReadonlyProperty,
Property,
MemberFunction,
Constructor,
};
inline std::string LuaSignatureKey(std::string_view key)
{
return StrCat("__sig_", key);
}
inline std::string LuaDocstringKey(std::string_view key)
{
return StrCat("__doc_", key);
}
inline std::string LuaUserdataMemberTypeKey(std::string_view key)
{
return StrCat("__udt_", key);
}
namespace lua_metadoc_internal {
template <typename U>
void SetUsertypeSignatureAndDocstring(sol::usertype<U> &table, std::string_view key, const char *signature, const char *doc, LuaUserdataMemberType memberType)
{
table.set(LuaSignatureKey(key), sol::var(signature));
table.set(LuaDocstringKey(key), sol::var(doc));
table.set(LuaUserdataMemberTypeKey(key), sol::var(static_cast<uint8_t>(memberType)));
}
inline void SetSignatureAndDocstring(sol::table &table, std::string_view key, const char *signature, const char *doc)
{
table.set(LuaSignatureKey(key), signature);
table.set(LuaDocstringKey(key), doc);
}
} // namespace lua_metadoc_internal
template <typename U, typename T>
void LuaSetDocFn(sol::usertype<U> &table, std::string_view key, const char *signature, const char *doc, T &&value)
{
table.set_function(key, std::forward<T>(value));
lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, signature, doc, LuaUserdataMemberType::MemberFunction);
}
template <typename U, typename G>
void LuaSetDocReadonlyProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, G &&getter)
{
table.set(key, sol::readonly_property(std::forward<G>(getter)));
lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::ReadonlyProperty);
}
template <typename U, typename G, typename S>
void LuaSetDocProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, G &&getter, S &&setter)
{
table.set(key, sol::property(std::forward<G>(getter), std::forward<S>(setter)));
lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property);
}
template <typename U, typename F>
void LuaSetDocProperty(sol::usertype<U> &table, std::string_view key, const char *type, const char *doc, F U::*&&value)
{
table.set(key, value);
lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property);
}
template <typename T>
void LuaSetDoc(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value)
{
table.set(key, std::forward<T>(value));
lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc);
}
template <typename T>
void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value)
{
table.set_function(key, std::forward<T>(value));
lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc);
}
template <typename T>
void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, T &&value)
{
table.set_function(key, std::forward<T>(value));
table.set(LuaSignatureKey(key), signature);
}
inline std::optional<std::string> GetSignature(const sol::table &table, std::string_view key)
{
return table.get<std::optional<std::string>>(LuaSignatureKey(key));
}
inline std::optional<std::string> GetDocstring(const sol::table &table, std::string_view key)
{
return table.get<std::optional<std::string>>(LuaDocstringKey(key));
}
inline std::optional<std::string> GetLuaUserdataSignature(const sol::userdata &obj, std::string_view key)
{
return obj.get<std::optional<std::string>>(LuaSignatureKey(key));
}
inline std::optional<std::string> GetLuaUserdataDocstring(const sol::userdata &obj, std::string_view key)
{
return obj.get<std::optional<std::string>>(LuaDocstringKey(key));
}
inline std::optional<LuaUserdataMemberType> GetLuaUserdataMemberType(const sol::userdata &obj, std::string_view key, const sol::object &value)
{
std::optional<uint8_t> result = obj.get<std::optional<uint8_t>>(LuaUserdataMemberTypeKey(key));
if (!result.has_value()) {
if (value.get_type() == sol::type::userdata) return LuaUserdataMemberType::Property;
if (value.get_type() == sol::type::function && key == "new") return LuaUserdataMemberType::Constructor;
return std::nullopt;
}
return static_cast<LuaUserdataMemberType>(*result);
}
} // namespace devilution