#pragma once #include #include #include #include #include #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 void SetUsertypeSignatureAndDocstring(sol::usertype &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(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 void LuaSetDocFn(sol::usertype &table, std::string_view key, const char *signature, const char *doc, T &&value) { table.set_function(key, std::forward(value)); lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, signature, doc, LuaUserdataMemberType::MemberFunction); } template void LuaSetDocReadonlyProperty(sol::usertype &table, std::string_view key, const char *type, const char *doc, G &&getter) { table.set(key, sol::readonly_property(std::forward(getter))); lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::ReadonlyProperty); } template void LuaSetDocProperty(sol::usertype &table, std::string_view key, const char *type, const char *doc, G &&getter, S &&setter) { table.set(key, sol::property(std::forward(getter), std::forward(setter))); lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property); } template void LuaSetDocProperty(sol::usertype &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 void LuaSetDoc(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value) { table.set(key, std::forward(value)); lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc); } template void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value) { table.set_function(key, std::forward(value)); lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc); } template void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, T &&value) { table.set_function(key, std::forward(value)); table.set(LuaSignatureKey(key), signature); } inline std::optional GetSignature(const sol::table &table, std::string_view key) { return table.get>(LuaSignatureKey(key)); } inline std::optional GetDocstring(const sol::table &table, std::string_view key) { return table.get>(LuaDocstringKey(key)); } inline std::optional GetLuaUserdataSignature(const sol::userdata &obj, std::string_view key) { return obj.get>(LuaSignatureKey(key)); } inline std::optional GetLuaUserdataDocstring(const sol::userdata &obj, std::string_view key) { return obj.get>(LuaDocstringKey(key)); } inline std::optional GetLuaUserdataMemberType(const sol::userdata &obj, std::string_view key, const sol::object &value) { std::optional result = obj.get>(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(*result); } } // namespace devilution