Search code examples
c++capnproto

Proper syntax to read and write byte array in Cap'n Proto?


Let's say I have an array:

struct UUID
{
    char data[16];
};

And I have it like so in the schema:

struct UUID
{
    value @0 : Data;
}

What's the proper way to read and write this field? It looks like I should be able to wrap a capnp::Data::Reader around the array and use the builder's setValue(), but the syntax is really non-obvious.

The other way is also somewhat mysterious. How do I populate the array when deserializing? My current approach involves a memcpy, but I assume there's a Cap'n Proto way to do it.


Solution

  • Data::Reader is essentially a kj::ArrayPtr<const kj::byte>.

    Data::Builder is essentially a kj::ArrayPtr<kj::byte>.

    kj::byte is a typedef for unsigned char.

    kj::ArrayPtr is essentially a pointer/size pair. It implements operator[], size(), begin(), end(), etc. begin() and end() return raw pointers, not a special iterator type.

    Building:

    UUID::Builder builder = ...;
    kj::byte buf[16] = ...;
    
    // option 1
    builder.setData(kj::arrayPtr(buf, sizeof(buf)));
    
    // option 2
    memcpy(builder.initData(16).begin(), buf, 16);
    

    Reading:

    UUID::Reader reader = ...;
    auto data = reader.getData();
    
    // option 1
    // void someFunction(kj::byte* ptr, size_t size)
    someFunction(data.begin(), data.size());
    
    // option 2
    kj::byte buf[16];
    KJ_REQUIRE(data.size() == sizeof(buf));
    memcpy(buf, data.begin(), sizeof(buf));