hideakitai / MsgPack

MessagePack implementation for Arduino (compatible with other C++ apps) / msgpack.org[Arduino]
MIT License
56 stars 3 forks source link

How to detect which type to unpack / deserialize? #20

Open cnf opened 4 days ago

cnf commented 4 days ago

Hi, if you get msgpack messages in, and they can be one of say 4 different formats, based on custom classes, how would you go about detecting which one to unpack?

I am trying to figure something out with unpackable, but that doesn't like custom classes, and I soft of have something working by just trying deserialize, and rewinding the index if it returns false, but that seems like a lot of overhead every time you get a message, especially if you have many types.

Is it not the point of msgpack compared to cpnproto or something that you are more flexible in your messages? Maybe I am misunderstanding something, but I'm afraid I can't quite figure it out.

Thanks

cnf commented 4 days ago

To add a bit more info, I am working with some example data

struct IntTopic : public Printable {
  MsgPack::str_t topic;
  int int_data;
  MSGPACK_DEFINE_MAP(topic, int_data);
  size_t printTo(Print &p) const { return p.printf("{ %s : %i }", topic.c_str(), int_data); }
};

struct StringTopic : public Printable {
  MsgPack::str_t topic;
  MsgPack::str_t string_data;
  MSGPACK_DEFINE_MAP(topic, string_data);
  size_t printTo(Print &p) const { return p.printf("{ %s : %s }", topic.c_str(), string_data.c_str()); }
};

and then I try do do


void Receive(char *data, uint16_t length) {
StringTopic string_payload;
  IntTopic int_payload;
  LOG_DEBUG("Received msg");
  hexdump((const unsigned char *)data, length);

  unpacker.feed((uint8_t *)data, length);
  int i = unpacker.index();

  if (unpacker.deserialize(int_payload)) {
    LOG_DEBUG("INT Message:", int_payload);
    unpacker.clear();
    return;
  }
  unpacker.index(i);
  if (unpacker.deserialize(string_payload)) {
    LOG_DEBUG("STR Message:", string_payload);
    unpacker.clear();
    return;
  }
  unpacker.index(i);
  /// etc for different message types
  unpacker.clear();
}
hideakitai commented 1 day ago

Your usage is almost OK based on your example. However, your understanding of the index is not correct.

  1. Use different endpoints for different types of message
  2. Use an index outside of msgpack (like MsgPacketizer)
  3. Use topic/type (as you did) and two-step deserialization