@@ -32,8 +32,12 @@ def read_float(buffer, offset, bit_size):
32
32
raise FlexbufferParseException ("Invalid bit size for flexbuffer float: %d" % bit_size )
33
33
34
34
35
- def read_string (buffer , offset , size ):
36
- return buffer [offset :offset + size ].decode ('utf-8' )
35
+ def read_string (buffer , offset , size , decode_strings ):
36
+ data = buffer [offset :offset + size ]
37
+ if decode_strings :
38
+ # Flexbuffer requires all strings to be valid UTF-8 but FlexOps don't always respect this.
39
+ data = data .decode ('utf-8' )
40
+ return data
37
41
38
42
39
43
def read_indirect (buffer , offset , bit_size ):
@@ -44,16 +48,16 @@ def read_bytes(buffer, offset, size):
44
48
return buffer [offset :offset + size ]
45
49
46
50
47
- def read_array (buffer , offset , length , bit_size , packed_type ):
51
+ def read_array (buffer , offset , length , bit_size , packed_type , decode_strings ):
48
52
byte_size = 1 << bit_size
49
53
arr = []
50
54
for i in range (length ):
51
55
item_offset = offset + (i * byte_size )
52
- arr .append (read_buffer (buffer , item_offset , bit_size , packed_type ))
56
+ arr .append (read_buffer (buffer , item_offset , bit_size , packed_type , decode_strings ))
53
57
return arr
54
58
55
59
56
- def read_buffer (buffer , offset , parent_bit_size , packed_type ):
60
+ def read_buffer (buffer , offset , parent_bit_size , packed_type , decode_strings ):
57
61
"""Recursively decode flatbuffer object into python representation"""
58
62
bit_size = packed_type & 3
59
63
value_type = packed_type >> 2
@@ -64,20 +68,22 @@ def read_buffer(buffer, offset, parent_bit_size, packed_type):
64
68
if value_type in [0x1 , 0x2 , 0x3 ]:
65
69
read_fn = {0x1 : read_int , 0x2 : read_uint , 0x3 : read_float }[value_type ]
66
70
return read_fn (buffer , offset , parent_bit_size )
67
- if value_type in [ 0x4 , 0x5 ] :
71
+ if value_type == 0x4 :
68
72
str_offset = read_indirect (buffer , offset , parent_bit_size )
69
73
size = 0
70
74
while read_int (buffer , str_offset + size , 0 ) != 0 :
71
75
size += 1
72
- return read_string (buffer , str_offset , size )
76
+ return read_string (buffer , str_offset , size , decode_strings )
73
77
if value_type == 0x5 :
74
78
str_offset = read_indirect (buffer , offset , parent_bit_size )
75
- size_byte_size = 1 << bit_size
79
+ size_bit_size = bit_size
80
+ size_byte_size = 1 << size_bit_size
76
81
size = read_uint (buffer , str_offset - size_byte_size , bit_size )
77
82
while read_int (buffer , str_offset + size , 0 ) != 0 :
78
83
size_byte_size <<= 1
79
- size = read_uint (buffer , str_offset - size_byte_size , bit_size )
80
- return read_string (buffer , str_offset , size )
84
+ size_bit_size += 1
85
+ size = read_uint (buffer , str_offset - size_byte_size , size_bit_size )
86
+ return read_string (buffer , str_offset , size , decode_strings )
81
87
if value_type in [0x6 , 0x7 , 0x8 ]:
82
88
read_fn = {0x6 : read_int , 0x7 : read_uint , 0x8 : read_float }[value_type ]
83
89
data_offset = read_indirect (buffer , offset , parent_bit_size )
@@ -93,10 +99,10 @@ def read_buffer(buffer, offset, parent_bit_size, packed_type):
93
99
obj = {}
94
100
for i in range (length ):
95
101
key_offset = keys_vector_offset + i * key_byte_size
96
- key = read_buffer (buffer , key_offset , key_bit_size , (0x4 << 2 ) | key_bit_size )
102
+ key = read_buffer (buffer , key_offset , key_bit_size , (0x4 << 2 ) | key_bit_size , decode_strings )
97
103
value_offset = values_offset + i * byte_size
98
104
value_packed_type = read_uint (buffer , packed_types_offset + i , 0 )
99
- value = read_buffer (buffer , value_offset , bit_size , value_packed_type )
105
+ value = read_buffer (buffer , value_offset , bit_size , value_packed_type , decode_strings )
100
106
obj [key ] = value
101
107
return obj
102
108
if value_type == 0xa :
@@ -107,21 +113,21 @@ def read_buffer(buffer, offset, parent_bit_size, packed_type):
107
113
for i in range (length ):
108
114
item_offset = items_offset + (i * byte_size )
109
115
packed_type = read_uint (buffer , packed_types_offset + i , 0 )
110
- arr .append (read_buffer (buffer , item_offset , bit_size , packed_type ))
116
+ arr .append (read_buffer (buffer , item_offset , bit_size , packed_type , decode_strings ))
111
117
return arr
112
118
if value_type in [0xb , 0xc , 0xd , 0xe , 0xf , 0x24 ]:
113
119
length_offset = read_indirect (buffer , offset , parent_bit_size ) - byte_size
114
120
length = read_uint (buffer , length_offset , bit_size )
115
121
item_value_type = value_type - 0xb + 0x1
116
122
packed_type = item_value_type << 2
117
123
items_offset = read_indirect (buffer , offset , parent_bit_size )
118
- return read_array (buffer , items_offset , length , bit_size , packed_type )
124
+ return read_array (buffer , items_offset , length , bit_size , packed_type , decode_strings )
119
125
if 0x10 <= value_type <= 0x18 :
120
126
length = (value_type - 0x10 ) // 3 + 2
121
127
value_type = ((value_type - 0x10 ) % 3 ) + 1
122
128
packed_type = value_type << 2
123
129
items_offset = read_indirect (buffer , offset , parent_bit_size )
124
- return read_array (buffer , items_offset , length , bit_size , packed_type )
130
+ return read_array (buffer , items_offset , length , bit_size , packed_type , decode_strings )
125
131
if value_type == 0x19 :
126
132
data_offset = read_indirect (buffer , offset , parent_bit_size )
127
133
size_offset = data_offset - byte_size
@@ -132,9 +138,9 @@ def read_buffer(buffer, offset, parent_bit_size, packed_type):
132
138
raise FlexbufferParseException ("Invalid flexbuffer value type %r" % value_type )
133
139
134
140
135
- def read_flexbuffer (buffer ):
141
+ def read_flexbuffer (buffer , decode_strings = True ):
136
142
byte_size = read_uint (buffer , len (buffer ) - 1 , 0 )
137
143
bit_size = {1 : 0 , 2 : 1 , 4 : 2 , 8 : 3 , 16 : 4 }[byte_size ]
138
144
packed_type = read_uint (buffer , len (buffer ) - 2 , 0 )
139
145
offset = len (buffer ) - 2 - byte_size
140
- return read_buffer (buffer , offset , bit_size , packed_type )
146
+ return read_buffer (buffer , offset , bit_size , packed_type , decode_strings )
0 commit comments