Search code examples
websocketcapnproto

How to distinguish between multiple messages types in Cap'n Proto?


I'm using Cap'n proto to send and retrieve messages between multiple clients and my websocket server.

Since I have only one websocket channel to send and receive data and various type of messages can be sent, I need a way to distinguish between then when trying to decode it.

How can this be done correctly in Cap'n proto?

I think this question is language agnostic, but if a language is needed, I have my server in Rust and clients in Rust, Go and Javascript, so a solution that works in all these languages would be much appreciated.


Solution

  • The best thing to do is create an outer struct which is a union of all the possible types. For example, if you have types Foo, Bar, and Baz, define a type like:

    struct Outer {
      union {
        foo @0 :Foo;
        bar @1 :Bar;
        baz @2 :Baz;
      }
    }
    

    How to access a union depends on the language, but usually there is a which() method that returns an enum value specifying which field is filled in, and then you use the regular getter methods for a nested struct.

    Note that both ends have to use this Outer type. You can't serialize a message with a root type of Foo and then parse it as an Outer -- the message has to be created with type Outer. In general there is no way to distinguish different Cap'n Proto types based on the bytes alone.