well, the same can be said about JSON :-)
is up to you to pick a between a full-fledged library that can speak a protocol/format, generate mapping to/from your language types
or use a minimal implementation of a codec that can only deal with your specific format (e.g. for the sake of reducing the size of your dependencies).
The nice thing about protobuf is that there is an IDL you can use to document your format. E.g.:
syntax = "proto3";
message Macaroon {
int32 version = 1;
bytes location = 2;
bytes id = 3;
repeated Caveat caveats = 4;
bytes signature = 5;
}
message Caveat {
bytes location = 1;
bytes id = 2;
bytes vid = 3;
}
This schema defines a precise and unambiguous binary encoding (It also allows you to pass that schema to a code generator and supporting library,
but that's another story).
It also offers a compact and practical way to perform backwards compatible extensions of the protocol.
Your encoding use a EOS separator between caveats, protobuf would prefix each caveat with a varint size. Apart from that and some minor
differences with which type tags are encoded there is no big difference.
Just in case you wonder: the protobuf encoding rules are not just an implementation details of the protobuf library, that is subject to arbitrary changes between releases.
This means it shouldn't be too hard to actually implement an encoder and a decoder that will follow the same rules and be devoid of any unwanted dependency
to big and complex projects (which is a concern I do understand). It's definitely way less code that what I see you have to encode JSON!
The reason I would personally prefer this approach is that if you describe the encoding with a protobuf IDL and match its encoding, anybody
can easily write a macaroon library in any language (ruby, js, $your_favourite_unpopular_language_here). (I'm talking about native impls, where just binding with the C library is impossible or undesirable).
Perhaps, I'm biased in favour of protobuf out of familiarity, perhaps there is a better widely used and understood binary encoding, with support for a wide range of languages out there and yet simple to implement (e.g. not, ehm ehm ASN.1).
Cheers,
Marko
PS: For a compact JSON library you can take a look at a library I co-authored:
https://docs.cesanta.com/frozen/master/; it also deals with string escaping. Note thee %V formatter is undocumented: it encodes the argument with base64. We designed it for embedded (as in <2K ram) use cases so it's very small and uses as little memory as possible.