Yeah, we are confusing transfer syntax and serialization. We don’t care about the transfer syntax – it’s the domain of the transport layer. What we care about is how do we implement field boundaries when they do not match with byte boundaries.
A field whose boundary does not match with a byte boundary has to occupy only a fraction of the byte. The question is: should the fraction be aligned left or right?
We have to define an ordering rule for bits within a byte. There are two sensible possibilities:
- Big-endian is when the most significant bit is considered to be first.
- Little-endian is when the least significant bit is considered to be first.
Suppose we have a field that takes three bits of a byte; let’s label its bits
f, and the unoccupied bits would be
x. Then, in the case of the big-endian format, the byte will be divided up as follows (MSB on the left, LSB on the right):
And the little-endian would be (same display: MSB on the left, LSB on the right):
Which bit is transmitted first is absolutely irrelevant.
Kent Lennartsson got back to me with a suggestion to “make as few changes between two versions as possible”, which translates into big-endian. He wrote other things on the subject as well but they do not relate directly to the discussion so I am omitting that.
Sergey said at the dev call that he is concerned about the fact that a byte-boundary-aligned number that takes n<8 bits will be represented on the wire as if it were shifted left by (8-n). In other words, suppose we have
uint3 x, x=1, then a serialized representation would be (1<<(8-3)) = 32. Then (x+1) would be (2<<(8-3)) = 64, (x+2) -> 96, etc.
I am not entirely against the little-endian format but my little experiment with PyUAVCAN (see PR 99, linked earlier) seems to indicate that it doesn’t really make things much more approachable. Whichever way you turn it, unaligned fields are a disaster and you can’t do anything about it.