- proto::parser will likely contain helper functions for parsing messages from a buffer, for now it will explicitly define message parsers for each available message. It also leverages the new unpacker API, which has type safety in mind. These messages should not be unstructured, so it doesn't make sense to use the token API.
71 lines
2.1 KiB
C++
71 lines
2.1 KiB
C++
//-----------------------------------------------------------------------------
|
|
// ___ __ _ _
|
|
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Author: Kurt Sassenrath
|
|
// Module: Proto
|
|
//
|
|
// Parser implementations for various msgpack messages.
|
|
//
|
|
// Copyright (c) 2023 Kurt Sassenrath.
|
|
//
|
|
// License TBD.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "parselink/proto/parser.h"
|
|
#include "parselink/logging.h"
|
|
|
|
#include "parselink/msgpack/core/unpacker.h"
|
|
|
|
namespace parselink {
|
|
namespace proto {
|
|
|
|
namespace {
|
|
|
|
logging::logger logger{"parser"};
|
|
|
|
constexpr auto assign(auto& param, msgpack::unpacker& unpacker) noexcept
|
|
-> tl::expected<void, error> {
|
|
auto do_assign = [¶m](auto&& v) { param = v; };
|
|
return unpacker.unpack<std::decay_t<decltype(param)>>()
|
|
.map(do_assign)
|
|
.map_error([](auto) { return error::bad_data; });
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
tl::expected<connect_message, error> parse_connect_message(
|
|
std::span<std::byte const> data) noexcept {
|
|
msgpack::unpacker unpacker(data);
|
|
connect_message msg;
|
|
|
|
constexpr static tl::unexpected<error> bad_data(error::bad_data);
|
|
|
|
auto type = unpacker.unpack<std::string_view>();
|
|
if (!type || type != "connect") return bad_data;
|
|
|
|
auto entries = unpacker.unpack<msgpack::map_desc>();
|
|
if (!entries) return bad_data;
|
|
|
|
for (auto i = entries->count; i != 0; --i) {
|
|
auto key = unpacker.unpack<std::string_view>();
|
|
if (!key) return bad_data;
|
|
if (key == "version") {
|
|
if (auto val = assign(msg.version, unpacker)) continue;
|
|
} else if (key == "user_id") {
|
|
if (auto val = assign(msg.user_id, unpacker)) continue;
|
|
}
|
|
logger.debug("Unknown key: {}", *key);
|
|
return bad_data;
|
|
}
|
|
|
|
return msg;
|
|
}
|
|
|
|
} // namespace proto
|
|
} // namespace parselink
|