Dict parsing question
Simon McVittie
smcv at collabora.com
Fri Dec 15 15:55:38 UTC 2023
On Fri, 15 Dec 2023 at 13:17:49 +1300, Lawrence D'Oliveiro wrote:
> Structs and dict entries are marshalled in the same way as their
> contents, but their alignment is always to an 8-byte boundary, even
> if their contents would normally be less strictly aligned.
>
> So the beginning of a struct or dict is 8-byte-aligned, but its
> individual entries are not necessarily so.
The beginning of a struct is 8-byte-aligned, and the individual elements
within that struct are not necessarily. That's correct.
It's misleading to say that the beginning of a dict is 8-byte-aligned,
because the D-Bus wire protocol does not really have dicts as a concept.
What it does have is arrays with element type "dict entry", which are
encoded as equivalent to arrays with element type struct. When we say
something like "a dict {string: variant}", it's really just shorthand for
"an array of dict entries, each containing a string and a variant".
When dealing with the wire protocol, it's important not to say "dict"
if you really mean "dict entry", or vice versa.
The array is *4*-byte aligned, the same as any other array (because it
starts with a 4-byte length). After the length, the dict entries inside
it are 8-byte aligned, the same as structs.
So for example the common a{sv} (dict with string keys and variant values)
has exactly the same wire-protocol encoding as an a(sv) (array of structs
where each struct contains a string and a variant).
And, if you have these messages (in a pseudocode similar to GVariant text
encoding):
# signature "uya{yy}"
(uint32 0x12345678, byte 1, @a{yy} {byte 2: byte 3, byte 4: byte 5})
# signature "ya{yy}"
(byte 1, @a{yy} {byte 2: byte 3, byte 4: byte 5})
they would serialize into little-endian D-Bus message bodies as:
78 56 34 12 01 00 00 00 # uint32 0x12345678, byte 01, 3 bytes padding
0a 00 00 00 00 00 00 00 # array length 0x0a = 10, 4 bytes padding
02 03 00 00 00 00 00 00 # byte 02, byte 03, 6 bytes padding
04 05 # byte 04, byte 05
and
01 00 00 00 0a 00 00 00 # byte 01, 3 bytes padding, array length 0x0a
02 03 00 00 00 00 00 00 # as above
04 05
In both cases if we say "the beginning of the dict", it's shorthand for
"the beginning of the array of dict-entries", which is the byte with
value 0x0a in these examples. As you can see, that will always be 4-byte
aligned (which is why each of those messages needs 3 bytes of padding
after the 0x01), but will not always be 8-byte aligned.
But, each dict-entry in the array (in this case starting with byte 0x02 or
0x04) *will* always be 8-byte aligned, which is why we need 6 bytes of
padding after "0x02 0x03" in each of those messages, and 4 bytes of padding
after the length "0x0a 0x00 0x00 0x00" in the first message only.
smcv
More information about the dbus
mailing list