//----------------------------------------------------------------------------- // ___ __ _ _ // / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __ // / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ / // / ___/ (_| | | \__ \ __/ /__| | | | | < // \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ . // //----------------------------------------------------------------------------- // 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 { auto do_assign = [¶m](auto&& v) { param = v; }; return unpacker.unpack>() .map(do_assign) .map_error([](auto) { return error::bad_data; }); } } // anonymous namespace tl::expected parse_connect_message( std::span data) noexcept { msgpack::unpacker unpacker(data); connect_message msg; constexpr static tl::unexpected bad_data(error::bad_data); auto type = unpacker.unpack(); if (!type || type != "connect") return bad_data; auto entries = unpacker.unpack(); if (!entries) return bad_data; for (auto i = entries->count; i != 0; --i) { auto key = unpacker.unpack(); 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