@@ -295,7 +295,7 @@ class COLOR(BASE_INT):
295
295
BIN_INT64 = b'\x0A '
296
296
BIN_END_ALT = b'\x0B '
297
297
298
- def binary_loads (b , mapper = dict , merge_duplicate_keys = True , alt_format = False , raise_on_remaining = True ):
298
+ def binary_loads (b , mapper = dict , merge_duplicate_keys = True , alt_format = False , field_names = None , raise_on_remaining = True ):
299
299
"""
300
300
Deserialize ``b`` (``bytes`` containing a VDF in "binary form")
301
301
to a Python object.
@@ -307,13 +307,17 @@ def binary_loads(b, mapper=dict, merge_duplicate_keys=True, alt_format=False, ra
307
307
``merge_duplicate_keys`` when ``True`` will merge multiple KeyValue lists with the
308
308
same key into one instead of overwriting. You can se this to ``False`` if you are
309
309
using ``VDFDict`` and need to preserve the duplicates.
310
+
311
+ ``field_names`` contains a list of field keys. Newer `appinfo.vdf` format
312
+ stores this at the very end of the file, and it is needed to deserialize
313
+ the binary VDF segments in that file
310
314
"""
311
315
if not isinstance (b , bytes ):
312
316
raise TypeError ("Expected s to be bytes, got %s" % type (b ))
313
317
314
- return binary_load (BytesIO (b ), mapper , merge_duplicate_keys , alt_format , raise_on_remaining )
318
+ return binary_load (BytesIO (b ), mapper , merge_duplicate_keys , alt_format , field_names , raise_on_remaining )
315
319
316
- def binary_load (fp , mapper = dict , merge_duplicate_keys = True , alt_format = False , raise_on_remaining = False ):
320
+ def binary_load (fp , mapper = dict , merge_duplicate_keys = True , alt_format = False , field_names = None , raise_on_remaining = False ):
317
321
"""
318
322
Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
319
323
binary VDF) to a Python object.
@@ -325,7 +329,13 @@ def binary_load(fp, mapper=dict, merge_duplicate_keys=True, alt_format=False, ra
325
329
``merge_duplicate_keys`` when ``True`` will merge multiple KeyValue lists with the
326
330
same key into one instead of overwriting. You can se this to ``False`` if you are
327
331
using ``VDFDict`` and need to preserve the duplicates.
332
+
333
+ ``field_names`` contains a list of field keys. Newer `appinfo.vdf` format
334
+ stores this at the very end of the file, and it is needed to deserialize
335
+ the binary VDF segments in that file
328
336
"""
337
+ use_field_indices = bool (field_names )
338
+
329
339
if not hasattr (fp , 'read' ) or not hasattr (fp , 'tell' ) or not hasattr (fp , 'seek' ):
330
340
raise TypeError ("Expected fp to be a file-like object with tell()/seek() and read() returning bytes" )
331
341
if not issubclass (mapper , Mapping ):
@@ -337,7 +347,14 @@ def binary_load(fp, mapper=dict, merge_duplicate_keys=True, alt_format=False, ra
337
347
int64 = struct .Struct ('<q' )
338
348
float32 = struct .Struct ('<f' )
339
349
340
- def read_string (fp , wide = False ):
350
+ def read_string (fp , wide = False , use_field_indices = False ):
351
+ if use_field_indices :
352
+ # Newer appinfo.vdf has the list of field names in an out-of-band
353
+ # table
354
+ index = int32 .unpack (fp .read (int32 .size ))[0 ]
355
+
356
+ return field_names [index ]
357
+
341
358
buf , end = b'' , - 1
342
359
offset = fp .tell ()
343
360
@@ -382,7 +399,9 @@ def read_string(fp, wide=False):
382
399
continue
383
400
break
384
401
385
- key = read_string (fp )
402
+ # If 'field_names' was provided, each key is an int32 value that
403
+ # corresponds to an entry in the field name array.
404
+ key = read_string (fp , use_field_indices = use_field_indices )
386
405
387
406
if t == BIN_NONE :
388
407
if merge_duplicate_keys and key in stack [- 1 ]:
0 commit comments