File indexing completed on 2024-12-15 05:02:05

0001 /*
0002     SPDX-FileCopyrightText: 2019 Ivan Čukić <ivan.cukic(at)kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #ifndef BLADE_TRANSPORT_H
0008 #define BLADE_TRANSPORT_H
0009 
0010 #include "ControllerMessage.h"
0011 
0012 #include <sstream>
0013 #include <iostream>
0014 
0015 #include <capnp/message.h>
0016 #include <capnp/serialize.h>
0017 #include <capnp/serialize-packed.h>
0018 #include <kj/std/iostream.h>
0019 
0020 #include <utils/overloaded.h>
0021 using std_ex::overloaded;
0022 
0023 #include "transport/protocol/controller_message.capnp.h"
0024 
0025 namespace blade::serialization {
0026 
0027 inline
0028 void writeToStdStream(const ControllerMessage &msg, std::ostream& out_)
0029 {
0030     capnp::MallocMessageBuilder builder;
0031 
0032     auto cm = builder.initRoot<protocol::ControllerMessage>();
0033 
0034     cm.setHost(msg.host.data());
0035     cm.setController(msg.controller.data());
0036 
0037     auto message = cm.initMessage();
0038 
0039     std::visit(
0040         overloaded {
0041             [&](const PingMessage &) { message.initPing(); },
0042             [&](const QueryMessage &msg) {
0043                 auto query = message.initQuery();
0044                 query.setId(msg.id);
0045                 query.setText(msg.text.toUtf8().data());
0046             },
0047             [&](const ErrorMessage &msg) {
0048                 auto error = message.initError();
0049                 error.setCode(msg.code);
0050                 error.setMessage(msg.message.data());
0051             },
0052         },
0053         msg.message);
0054 
0055     kj::std::StdOutputStream out(out_);
0056     capnp::writeMessage(out, builder);
0057 }
0058 
0059 void writeToStdStream(const ControllerMessage &msg, std::ostream& out);
0060 
0061 inline
0062 std::string asStdString(const ControllerMessage& msg)
0063 {
0064     std::ostringstream result;
0065     writeToStdStream(msg, result);
0066     return result.str();
0067 }
0068 
0069 namespace detail {
0070     auto asByteArray(const capnp::Text::Reader& reader)
0071     {
0072         return QByteArray(reader.cStr(), reader.size());
0073     }
0074 } // namespace detail
0075 
0076 inline
0077 blade::ControllerMessage readControllerMessage(const std::string &data)
0078 {
0079     std::istringstream ss(data);
0080     kj::std::StdInputStream is(ss);
0081     capnp::InputStreamMessageReader reader(is);
0082 
0083     auto cm = reader.getRoot<protocol::ControllerMessage>();
0084 
0085     blade::ControllerMessage result;
0086 
0087     result.host = detail::asByteArray(cm.getHost());
0088     result.controller = detail::asByteArray(cm.getController());
0089 
0090     auto message = cm.getMessage();
0091 
0092     if (message.hasQuery()) {
0093         auto query = message.getQuery();
0094         result.message = blade::QueryMessage{
0095             query.getId(),
0096             QString::fromUtf8(detail::asByteArray(query.getText()))
0097         };
0098 
0099     } else if (message.hasPing()) {
0100         result.message = blade::PingMessage{};
0101 
0102     } else if (message.hasError()) {
0103         auto error = message.getError();
0104         result.message = blade::ErrorMessage{
0105             error.getCode(),
0106             detail::asByteArray(error.getMessage())
0107         };
0108 
0109     } else {
0110         result.message = blade::ErrorMessage{
0111             static_cast<std::uint16_t>(-1),
0112             "unknown error"
0113         };
0114     }
0115 
0116     return result;
0117 }
0118 
0119 
0120 } // namespace blade::serialization
0121 
0122 #endif // include guard
0123