| 125 | |
| 126 | |
| 127 | def _decode_value(typ, value): |
| 128 | if value is None: |
| 129 | return None |
| 130 | kind = typ['kind'] |
| 131 | if kind == 'primitive': |
| 132 | name = typ['name'] |
| 133 | if name in ['uint8', 'uint16', 'uint32', 'uint64', |
| 134 | 'int8', 'int16', 'int32', 'int64']: |
| 135 | return int(value) |
| 136 | if name == 'duration': |
| 137 | return durationpy.from_str(value) |
| 138 | if name == 'time': |
| 139 | return dateutil.parser.isoparse(value) |
| 140 | if name in ['float16', 'float32', 'float64']: |
| 141 | return float(value) |
| 142 | if name == 'decimal': |
| 143 | return decimal.Decimal(value) |
| 144 | if name == 'bool': |
| 145 | return value == 'true' |
| 146 | if name == 'bytes': |
| 147 | return binascii.a2b_hex(value[2:]) |
| 148 | if name == 'string': |
| 149 | return value |
| 150 | if name == 'ip': |
| 151 | return ipaddress.ip_address(value) |
| 152 | if name == 'net': |
| 153 | return ipaddress.ip_network(value) |
| 154 | if name in 'type': |
| 155 | return value |
| 156 | if name == 'null': |
| 157 | return None |
| 158 | raise Exception(f'unknown primitive name {name}') |
| 159 | if kind == 'record': |
| 160 | return {f['name']: _decode_value(f['type'], v) |
| 161 | for f, v in zip(typ['fields'], value)} |
| 162 | if kind == 'array': |
| 163 | return [_decode_value(typ['type'], v) for v in value] |
| 164 | if kind == 'set': |
| 165 | return {_decode_value(typ['type'], v) for v in value} |
| 166 | if kind == 'map': |
| 167 | key_type, val_type = typ['key_type'], typ['val_type'] |
| 168 | return {_decode_value(key_type, v[0]): _decode_value(val_type, v[1]) |
| 169 | for v in value} |
| 170 | if kind == 'union': |
| 171 | type_index, val = value |
| 172 | return _decode_value(typ['types'][int(type_index)], val) |
| 173 | if kind == 'enum': |
| 174 | return typ['symbols'][int(value)] |
| 175 | if kind in ['error', 'named']: |
| 176 | return _decode_value(typ['type'], value) |
| 177 | raise Exception(f'unknown type kind {kind}') |
| 178 | |
| 179 | |
| 180 | if __name__ == '__main__': |