From: Remi Gacogne Date: Mon, 8 Dec 2025 14:05:39 +0000 (+0100) Subject: LuaWrapper: Add support for `std::variant` X-Git-Tag: rec-5.4.0-beta1~57^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b52a4657af650544410123576ee2e1387416923;p=thirdparty%2Fpdns.git LuaWrapper: Add support for `std::variant` Signed-off-by: Remi Gacogne --- diff --git a/ext/luawrapper/include/LuaContext.hpp b/ext/luawrapper/include/LuaContext.hpp index 7bc2a74795..7a333dd444 100644 --- a/ext/luawrapper/include/LuaContext.hpp +++ b/ext/luawrapper/include/LuaContext.hpp @@ -47,6 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -2556,6 +2557,23 @@ private: }; }; +// std::variant +template +struct LuaContext::Pusher> +{ + static const int minSize = PusherMinSize::size; + static const int maxSize = PusherMaxSize::size; + + static PushedObject push(lua_State* state, const std::variant& value) noexcept { + PushedObject obj{state, 0}; + std::visit([&](auto&& arg) { + using T = std::decay_t; + obj = Pusher::push(state, arg); + }, value); + return obj; + } +}; + // boost::optional template struct LuaContext::Pusher> { @@ -2961,7 +2979,7 @@ struct LuaContext::Reader> }; // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) -// variant +// boost::variant template struct LuaContext::Reader> { @@ -3008,6 +3026,36 @@ public: } }; +// std::variant +template +struct LuaContext::Reader> +{ + using ReturnType = std::variant; + +private: + template static boost::optional variantRead(lua_State* state, int index) + { + constexpr auto nbTypes = std::variant_size_v; + if constexpr (I >= nbTypes) { + return boost::none; + } + if (const auto val = Reader>::read(state, index)) { + return ReturnType{*val}; + } + if constexpr (I < (nbTypes - 1)) { + return variantRead(state, index); + } + return boost::none; + } + +public: + static auto read(lua_State* state, int index) + -> boost::optional + { + return variantRead(state, index); + } +}; + // reading a tuple // tuple have an additional argument for their functions, that is the maximum size to read // if maxSize is smaller than the tuple size, then the remaining parameters will be left to default value diff --git a/pdns/test-luawrapper.cc b/pdns/test-luawrapper.cc index cd61d89ca4..9aae68dca8 100644 --- a/pdns/test-luawrapper.cc +++ b/pdns/test-luawrapper.cc @@ -70,4 +70,31 @@ BOOST_AUTO_TEST_CASE(test_std_optional) } } +BOOST_AUTO_TEST_CASE(test_std_variant) +{ + LuaContext context; + context.writeFunction("testVariant", [](std::variant incoming) -> std::variant { + return incoming; + }); + + { + auto result = context.executeCode>("return testVariant(1)"); + BOOST_REQUIRE(std::holds_alternative(result)); + BOOST_CHECK_EQUAL(std::get(result), 1); + } + + { + auto result = context.executeCode>("return testVariant('foo')"); + BOOST_REQUIRE(std::holds_alternative(result)); + BOOST_CHECK_EQUAL(std::get(result), "foo"); + } + + { + auto func = [&]() { + context.executeCode>("return testVariant(nil)"); + }; + BOOST_CHECK_THROW(func(), LuaContext::ExecutionErrorException); + } +} + BOOST_AUTO_TEST_SUITE_END()