NETCONF: support variable-return-type RPCs

This will become visible with user-defined RPCs which might return some
data, but also just the NETCONF-level <ok/>.

Change-Id: I1be572e7010e1c8a846822f8c7696bc5219d359b
diff --git a/src/netconf-client.cpp b/src/netconf-client.cpp
index f1cdfe2..a761bb4 100644
--- a/src/netconf-client.cpp
+++ b/src/netconf-client.cpp
@@ -162,7 +162,7 @@
     return client::ReportedError{ss.str()};
 }
 
-unique_ptr_for<struct nc_reply_data> do_rpc_data(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
+std::optional<unique_ptr_for<struct nc_reply_data>> do_rpc_data_or_ok(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
 {
     auto x = do_rpc(session, std::move(rpc));
 
@@ -170,27 +170,29 @@
     case NC_RPL_DATA:
         return guarded(reinterpret_cast<struct nc_reply_data*>(x.release()));
     case NC_RPL_OK:
-        throw std::runtime_error{"Received OK instead of a data reply"};
+        return std::nullopt;
     case NC_RPL_ERROR:
         throw make_error(std::move(x));
     default:
         throw std::runtime_error{"Unhandled reply type"};
     }
+
+}
+
+unique_ptr_for<struct nc_reply_data> do_rpc_data(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
+{
+    auto x = do_rpc_data_or_ok(session, std::move(rpc));
+    if (!x) {
+        throw std::runtime_error{"Received OK instead of a data reply"};
+    }
+    return std::move(*x);
 }
 
 void do_rpc_ok(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
 {
-    auto x = do_rpc(session, std::move(rpc));
-
-    switch (x->type) {
-    case NC_RPL_DATA:
+    auto x = do_rpc_data_or_ok(session, std::move(rpc));
+    if (x) {
         throw std::runtime_error{"Unexpected DATA reply"};
-    case NC_RPL_OK:
-        return;
-    case NC_RPL_ERROR:
-        throw make_error(std::move(x));
-    default:
-        throw std::runtime_error{"Unhandled reply type"};
     }
 }
 }