parselink-old/source/proto/parser.cpp

76 lines
2.2 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 {
logging::logger logger{"parser"};
}
namespace proto {
namespace {
constexpr auto assign(auto& param, msgpack::unpacker& unpacker) noexcept
-> tl::expected<void, error> {
auto do_assign = [&param](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_message::name()) 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
parselink::logging::logger& parselink::get_logger() { return logger; }