Program Listing for File register_cmd_parser.cpp

Return to documentation for file (register_cmd_parser.cpp)

#include "register_cmd_parser.hpp"
#include <nlohmann/json.hpp>
#include <format>
#include <string>


std::vector<ReqData> RegisterMsgParser::parse_commands(const char* msg, size_t len)
{
    std::vector<ReqData> parsed_messages;
    simdjson::dom::element ops = parser.parse(simdjson::padded_string(msg, len));
    simdjson::dom::array cmd_args;

    for (simdjson::dom::object op : ops) {
        ReqData parsed_msg;
        //Parse UUID
        std::string_view uuid_view = "";
        parsed_msg.status_code = op[FelixClientThread::to_string(FelixClientThread::UUID)].get(uuid_view);
        if (parsed_msg.status_code) {
            parsed_msg.status_message = "Field 'uuid' not found";
        }
        parsed_msg.uuid = std::string(uuid_view);

        //Parse CMD
        std::string_view cmd_view = "";
        if (!parsed_msg.status_code) {
            parsed_msg.status_code = op[FelixClientThread::to_string(FelixClientThread::CMD)].get(cmd_view);
            if (parsed_msg.status_code) {
                parsed_msg.status_message = "Field 'cmd' not found";
            }
        }
        parsed_msg.cmd = FelixClientThread::to_cmd(std::string(cmd_view));

        //Parse register name and value
        if (!parsed_msg.status_code) {
            parsed_msg.status_code = op[FelixClientThread::to_string(FelixClientThread::CMD_ARGS)].get(cmd_args);
            if (parsed_msg.status_code) {
                parsed_msg.status_message = "Field 'cmd_args' not found";
            } else {
                for (unsigned int i = 0; i < cmd_args.size(); ++i) {
                    if ( i == 0 ) {parsed_msg.resource_name = std::string(cmd_args.at(i));}
                    else if ( i == 1 ) {parsed_msg.value = std::string(cmd_args.at(i));}
                    else {
                        parsed_msg.status_message = "Field 'cmd_args' not found";
                    }
                }
            }
        }

        if (parsed_msg.status_code == FelixClientThread::OK){
            parse_cmd_args(parsed_msg, cmd_args);
        }

        parsed_messages.push_back(parsed_msg);
    }

    return parsed_messages;
}


void RegisterMsgParser::parse_cmd_args(ReqData& msg, simdjson::dom::array& arr)
{
    switch(msg.cmd) {
        case FelixClientThread::Cmd::UNKNOWN:
        case FelixClientThread::TRIGGER: {  //TRIGGER not supported yet.
            msg.status_code = FelixClientThread::Status::ERROR_INVALID_CMD;
            msg.value = "";
            msg.status_message = "Invalid command";
            break;
        }
        case FelixClientThread::Cmd::NOOP: {
            if (arr.size() != 0) {
                msg.status_code = FelixClientThread::ERROR_INVALID_ARGS;
                msg.value = "";
                msg.status_message = std::string("Invalid number of arguments, found ") + std::to_string(arr.size()) + ", 0 expected.";
            }
            break;
        }
        case FelixClientThread::Cmd::GET: {
            if (arr.size() != 1) {
                msg.status_code = FelixClientThread::ERROR_INVALID_ARGS;
                msg.value = "";
                msg.status_message = std::string("Invalid number of arguments, found ") + std::to_string(arr.size()) + ", 1 expected.";
            } else {
                msg.resource_name = std::string(arr.at(0));
            }
            break;
        }
        case FelixClientThread::ECR_RESET: {
            if (arr.size() != 1) {
                msg.status_code = FelixClientThread::ERROR_INVALID_ARGS;
                msg.value = "";
                msg.status_message = std::string("Invalid number of arguments, found ") + std::to_string(arr.size()) + ", 1 expected.";
            } else {
                msg.value = std::string(arr.at(0));
            }
            break;
        }
        case FelixClientThread::Cmd::SET: {
            if (arr.size() != 2) {
                msg.status_code = FelixClientThread::ERROR_INVALID_ARGS;
                msg.value = "";
                msg.status_message = std::string("Invalid number of arguments, found ") + std::to_string(arr.size()) + ", 2 expected.";
            } else {
                msg.resource_name = std::string(arr.at(0));
                msg.value = std::string(arr.at(1));
            }
            break;
        }
    }
}


std::vector<ReqData> RegisterMsgParser::parse_commands(const std::string& cmd)
{
    return parse_commands(cmd.c_str(), cmd.size());
}


std::string RegisterMsgParser::encode_commands(const std::vector<Command> & cmds)
{
    nlohmann::json j = nlohmann::json::array();
    for (unsigned int i = 0; i < cmds.size(); ++i) {
        auto & entry = cmds[i];
        j[i][FelixClientThread::to_string(FelixClientThread::UUID)]  = entry.uuid;
        j[i][FelixClientThread::to_string(FelixClientThread::CMD)]   = FelixClientThread::to_string(entry.cmd);
        j[i][FelixClientThread::to_string(FelixClientThread::CMD_ARGS)]  = nlohmann::json(entry.cmd_args);
    }
    return j.dump();
}



std::string RegisterMsgParser::encode_replies(uint64_t fid, const std::vector<ReqData>& cmds)
{
    nlohmann::json j = nlohmann::json::array();
    for (unsigned int i = 0; i < cmds.size(); ++i) {
        const auto & entry = cmds[i];
        j[i]["ctrl_fid"] = std::format("{:#0x}", fid);
        j[i][FelixClientThread::to_string(FelixClientThread::UUID)]    = entry.uuid;
        j[i][FelixClientThread::to_string(FelixClientThread::STATUS)]  = entry.status_code;
        j[i][FelixClientThread::to_string(FelixClientThread::MESSAGE)] = entry.status_message;
        j[i][FelixClientThread::to_string(FelixClientThread::VALUE)]   = (entry.value == "") ? 0 : std::stoul(entry.value, nullptr, 0);
    }
    return j.dump();
}


std::vector<FelixClientThread::Reply> RegisterMsgParser::decode_replies(const std::string & r)
{
    std::vector<FelixClientThread::Reply> replies;
    auto key_status = FelixClientThread::to_string(FelixClientThread::STATUS);
    auto key_value = FelixClientThread::to_string(FelixClientThread::VALUE);
    auto key_msg = FelixClientThread::to_string(FelixClientThread::MESSAGE);

    auto j = nlohmann::json::parse(r);
    for (const auto& item : j.items()) {

        auto entry = item.value();

        auto num_value = entry[key_value].template get<std::uint64_t>();
        //unsigned long num_value = value.empty() ? 0 : std::stoul(value, nullptr, 16);
        int status = static_cast<FelixClientThreadExtension::Status>(entry[key_status].template get<int>());

        replies.emplace_back(
            FelixClientThread::Reply {
                .ctrl_fid = std::stoul(entry["ctrl_fid"].template get<std::string>(), nullptr, 16),
                .status  = static_cast<FelixClientThread::Status>(status),
                .value   = num_value,
                .message = entry[key_msg].template get<std::string>(),
            }
        );
    };
    return replies;
}