Selecting the correct message type?

20 views
Skip to first unread message

SR D

unread,
Jul 17, 2021, 12:55:08 PMJul 17
to Cap'n Proto
If the sender is sending any number of different data types that have been serialized across the network, how does one know which type is coming in so that it can be pulled off using FlatArrayMessageReader's::getRoot<>?

E.g., say this while loop is constantly reading serialized data from the network and results in a vector of message buffers.

        for (auto& msg : messages) {
            auto arr = kj::ArrayPtr<const capnp::word>(
                reinterpret_cast<const capnp::word*>(msg),
                size / sizeof(capnp::word));
                
            capnp::FlatArrayMessageReader reader(arr);

            // how would one know what type to use here?
            auto msg = reader.getRoot<?>();
        }

Kenton Varda

unread,
Jul 17, 2021, 1:22:10 PMJul 17
to SR D, Cap'n Proto
There is no way to find out a message's type if you don't know it already. So, you'll need to arrange to communicate the type yourself. The easiest way is to write an "envelope" message that is a union of all your other messages.

struct OuterMessage {
  union {
    foo @0 :FooMessage;
    bar @1 :BarMessage;
    baz @2 :BazMessage;
  }
}

Then, always send OuterMessage as the top-level message type.

-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/capnproto/c89926fe-3b18-4e0f-9d30-8f8134b78a0an%40googlegroups.com.

SR D

unread,
Jul 19, 2021, 4:45:08 PMJul 19
to Cap'n Proto
Ok, so after some thinking, I can put something together to communicate the type. Let's say I now know the type upon receiving the data, I make this call ...

    auto m = reader.getRoot<Person>();
    
Here, m is of type myns::Person::Reader. So although I know the type, I looked at the person.capnp.h file and found no way to get a handle to the actual data I care about, the myns::Person object, rather just the getters.

I understand I can rebuild the object by calling the individual fields like m.getXXX()'s, but I'm trying to do this in a generic way and not have to call the individual fields to get a myns::Person and pass the object to another thread for processing. So, my goal is to not have to call any proto object methods (getters or setters) and hope to call something from the Reader to get some sort of reference to the object since I know it's type.

Is that possible?

Kenton Varda

unread,
Jul 19, 2021, 5:56:51 PMJul 19
to SR D, Cap'n Proto
Sorry, I'm not sure what you mean. `myns::Person` isn't a real type, it's just an empty class that acts as a namespace containing the `Reader` and `Builder` types. `Reader` is your "handle to the data", and its getters are the only way to read the underlying data (the getters read directly from the raw underlying byte buffer).

-Kenton

SR D

unread,
Jul 19, 2021, 6:16:03 PMJul 19
to Cap'n Proto
Ok, thanks for clearing that up for me.

SR D

unread,
Jul 19, 2021, 6:16:57 PMJul 19
to Cap'n Proto
Maybe I'll look into carrying the byte buffer around then.
Reply all
Reply to author
Forward
0 new messages