I find this works pretty well in practice. EDN and transit are two s-expression based formats that come from Clojure, but have libraries available in a variety of languages as well.
It’s worth taking a look at @rain1’s https://gist.github.com/rain-1/a253e47b939fc0769524d8716541c96e .
Interesting idea, but it doesn’t distinguish between an empty bytestring and an empty list.
As far as I can see, it doesn’t have any notion of “byte”. But for normal strings, it’s a string of length 0.
It’s length-prefixed, like the canonical S-expressions which inspired it, and mentions byte equivalency, so I think it has to be byte-oriented.
It’s a notation for lists represented as dotted pairs, but its pair notation can’t be used directly because there’s no way to distinguish ("a") from ('a" . ""). With normal NIL-terminated lists that’s okay, because NIL is special in a way that I think the empty string is not.
('a" . "")
But maybe I’m wrong.
Unless I am completely missing something, this is what I have come up with:
("a" . ""):
Ah, I was looking at his basic format, not the extended one.
The extended one is definitely the interesting one :)