Fix for Boost 1.78

New Boost does not revert iterators in some cases, so reverting must be
done manually.

About the command_completion change: I have no idea, but the 1.77 fix
works for 1.78.

This actually needs this patch
https://github.com/boostorg/spirit/pull/711. No idea how to inject that
to the CI.

Issue: https://github.com/boostorg/spirit/issues/703#issuecomment-1011021773
Change-Id: I2d1266b1f8b893f180ae36842bdfdb35c5629ea4
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 288801d..352824e 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -16,6 +16,9 @@
 #include "ast_commands.hpp"
 #include "parser_context.hpp"
 #include "schema.hpp"
+#if BOOST_VERSION >= 107800
+#include "UniqueResource.hpp"
+#endif
 #include "utils.hpp"
 namespace x3 = boost::spirit::x3;
 
@@ -153,10 +156,30 @@
     }
 };
 
+#if BOOST_VERSION >= 107800
+template <typename Iterator>
+[[nodiscard]] auto makeIteratorRollbacker(Iterator const& was, Iterator& will, bool& passFlag)
+{
+    return make_unique_resource([] {},
+    [&was, &will, &passFlag] {
+        if (!passFlag) {
+            will = was;
+        }
+    });
+}
+#endif
+
 struct presenceContainerPath_class {
     template <typename T, typename Iterator, typename Context>
+#if BOOST_VERSION >= 107800
+    void on_success(Iterator const& was, Iterator& will, T& ast, Context const& context)
+#else
     void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+#endif
     {
+#if BOOST_VERSION >= 107800
+        auto rollback = makeIteratorRollbacker(was, will, _pass(context));
+#endif
         auto& parserContext = x3::get<parser_context_tag>(context);
         const auto& schema = parserContext.m_schema;
         if (ast.m_nodes.empty()) {
@@ -174,8 +197,15 @@
 
 struct listInstancePath_class {
     template <typename T, typename Iterator, typename Context>
+#if BOOST_VERSION >= 107800
+    void on_success(Iterator const& was, Iterator& will, T& ast, Context const& context)
+#else
     void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+#endif
     {
+#if BOOST_VERSION >= 107800
+        auto rollback = makeIteratorRollbacker(was, will, _pass(context));
+#endif
         auto& parserContext = x3::get<parser_context_tag>(context);
         if (ast.m_nodes.empty() || !std::holds_alternative<listElement_>(ast.m_nodes.back().m_suffix)) {
             parserContext.m_errorMsg = "This is not a list instance.";
@@ -186,8 +216,15 @@
 
 struct leafListElementPath_class {
     template <typename T, typename Iterator, typename Context>
+#if BOOST_VERSION >= 107800
+    void on_success(Iterator const& was, Iterator& will, T& ast, Context const& context)
+#else
     void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+#endif
     {
+#if BOOST_VERSION >= 107800
+        auto rollback = makeIteratorRollbacker(was, will, _pass(context));
+#endif
         auto& parserContext = x3::get<parser_context_tag>(context);
         if (ast.m_nodes.empty() || !std::holds_alternative<leafListElement_>(ast.m_nodes.back().m_suffix)) {
             parserContext.m_errorMsg = "This is not a leaf list element.";
@@ -379,10 +416,17 @@
 
 struct createCommandSuggestions_class {
     template <typename T, typename Iterator, typename Context>
-    void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
+#if BOOST_VERSION >= 107800
+    void on_success(Iterator const& was, Iterator& will, T&, Context const& context)
+#else
+    void on_success(Iterator const& was, Iterator const&, T&, Context const& context)
+#endif
     {
+#if BOOST_VERSION >= 107800
+        auto rollback = makeIteratorRollbacker(was, will, _pass(context));
+#endif
         auto& parserContext = x3::get<parser_context_tag>(context);
-        parserContext.m_completionIterator = begin;
+        parserContext.m_completionIterator = was;
 
         parserContext.m_suggestions.clear();
         boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([&parserContext](auto cmd) {