Search code examples
c++protocol-bufferscode-duplication

c++ parsing protobuf messages with switch/case (reducing duplicate code)


I'm trying to build server application program parsing protobuf packets from client.

packet processing codes are like below :

in proto file,

package protocol;

message messageA
{
    ...
}

message messageB
{
    ...
}

message messageB
{
    ...
}

...

in code file,

enum {
    messageTypeA = 1,
    messageTypeB, 
    messageTypeC, 
...
}

void ProcessPacket(int protocolID, char* packetData)
{
    string messageTypeString = "";

    switch(protocolID)
    {
        case messageTypeA : 
            protocol::messageA packet;

            packet.ParseFromArray(packetData, sizeof(padketData));

            messageTypeString = "messageA";

            ...    //kind of logging packet procedure

            break;
        case messageTypeB : 
            protocol::messageB packet;

            packet.ParseFromArray(packetData, sizeof(padketData));

            messageTypeString = "messageB";

            ...    //kind of logging packet procedure

            break;
        case messageTypeC : 
            protocol::messageC packet;

            packet.ParseFromArray(packetData, sizeof(padketData));

            messageTypeString = "messageC";

            ...    //kind of logging packet procedure

            break;
    }

    //using messageTypeString and so on..
}

As we can see, when packet kind grows, there are so many duplicated code.

How can I reducing duplicated code?

Is there any way to mapping protocolID(enum value), type of packet and messageTypeString at once?


Solution

  • You could do something along these lines, I suppose:

    std::map<int, std::unique_ptr<google::protobuf::Message>> protocols = {
      {messageTypeA, std::make_unique<protocol::messageA>()},
      {messageTypeB, std::make_unique<protocol::messageB>()},
      {messageTypeC, std::make_unique<protocol::messageC>()}
    };
    
    void ProcessPacket(int protocolID, char* packetData, int packetSize) {
      auto it = protocols.find(protocolID);
      assert(it != protocols.end());
      std::unique_ptr<google::protobuf::Message> packet{it->second->New()};
      packet->ParseFromArray(packetData, packetSize);
      std::string messageTypeString = packet->GetTypeName();
      //kind of logging packet procedure goes here
    }
    

    Hopefully, your "kind of logging procedure" can work in terms of generic Message