From: Remi Gacogne Date: Tue, 22 Jul 2025 12:05:56 +0000 (+0200) Subject: LuaWrapper: Add support for `std::optional` X-Git-Tag: auth-5.1.0-alpha0~16^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61f904b9d588767451ed7506bbad360f4ae12ee1;p=thirdparty%2Fpdns.git LuaWrapper: Add support for `std::optional` Signed-off-by: Remi Gacogne --- diff --git a/ext/luawrapper/include/LuaContext.hpp b/ext/luawrapper/include/LuaContext.hpp index 655375e7c9..66f879eb83 100644 --- a/ext/luawrapper/include/LuaContext.hpp +++ b/ext/luawrapper/include/LuaContext.hpp @@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -1873,8 +1874,8 @@ private: // the only case where "min != max" is with boost::optional at the end of the list template struct FunctionArgumentsCounter {}; - - // true is the template parameter is a boost::optional + + // true if the template parameter is a boost::optional or std::optional template struct IsOptional : public std::false_type {}; }; @@ -1970,6 +1971,8 @@ struct LuaContext::FunctionArgumentsCounter<> { // implementation of IsOptional template struct LuaContext::IsOptional> : public std::true_type {}; +template +struct LuaContext::IsOptional> : public std::true_type {}; // implementation of LuaFunctionCaller template @@ -2542,6 +2545,25 @@ struct LuaContext::Pusher> { } }; +// std::optional +template +struct LuaContext::Pusher> { + typedef Pusher::type> + UnderlyingPusher; + + static const int minSize = UnderlyingPusher::minSize < 1 ? UnderlyingPusher::minSize : 1; + static const int maxSize = UnderlyingPusher::maxSize > 1 ? UnderlyingPusher::maxSize : 1; + + static PushedObject push(lua_State* state, const std::optional& value) noexcept { + if (value.has_value()) { + return UnderlyingPusher::push(state, value.value()); + } else { + lua_pushnil(state); + return PushedObject{state, 1}; + } + } +}; + // tuple template struct LuaContext::Pusher> { @@ -2891,6 +2913,22 @@ struct LuaContext::Reader> } }; +template +struct LuaContext::Reader> +{ + static auto read(lua_State* state, int index) + -> boost::optional> + { + if (lua_isnil(state, index)) { + return boost::optional>{std::optional()}; + } + if (auto&& other = Reader::read(state, index)) { + return std::move(std::optional(*other)); + } + return boost::none; + } +}; + // variant template struct LuaContext::Reader> diff --git a/pdns/test-luawrapper.cc b/pdns/test-luawrapper.cc index dd01254db9..c4d2e34921 100644 --- a/pdns/test-luawrapper.cc +++ b/pdns/test-luawrapper.cc @@ -35,3 +35,39 @@ BOOST_AUTO_TEST_CASE(test_registerFunction) } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(test_luawrapper) + +BOOST_AUTO_TEST_CASE(test_boost_optional) +{ + LuaContext context; + context.writeFunction("testOptional", [](boost::optional in) -> boost::optional { + return in; + }); + + BOOST_REQUIRE(!context.executeCode>("return testOptional(nil)")); + + { + auto result = context.executeCode>("return testOptional(1)"); + BOOST_REQUIRE(result); + BOOST_CHECK_EQUAL(*result, 1); + } +} + +BOOST_AUTO_TEST_CASE(test_std_optional) +{ + LuaContext context; + context.writeFunction("testOptional", [](std::optional in) -> std::optional { + return in; + }); + + BOOST_REQUIRE(!context.executeCode>("return testOptional(nil)")); + + { + auto result = context.executeCode>("return testOptional(1)"); + BOOST_REQUIRE(result); + BOOST_CHECK_EQUAL(*result, 1); + } +} + +BOOST_AUTO_TEST_SUITE_END()