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