Dict parsing question

Robert Middleton robert.middleton at rm5248.com
Fri Dec 15 17:59:34 UTC 2023


Simon,

Thanks, I realized what I was doing wrong last night as soon as I
tried to go to sleep(why do insights always happen just as you're
about to sleep?)  Basically it's not recursing properly into the
variant for some reason, and because the strings happen to start on
8-byte boundaries it parses some of them but then dies once the string
is not on the 8-byte boundary.

-Robert Middleton

On Fri, Dec 15, 2023 at 10:55 AM Simon McVittie <smcv at collabora.com> wrote:
>
> 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