| 1 | def serialize(val, typ=None): |
| 2 | if typ is None and hasattr(val, 'fields'): |
| 3 | typ = type(val) |
| 4 | if typ in ('hash32', 'address'): |
| 5 | assert len(val) == 20 if typ == 'address' else 32 |
| 6 | return val |
| 7 | elif isinstance(typ, str) and typ[:3] == 'int': |
| 8 | length = int(typ[3:]) |
| 9 | assert length % 8 == 0 |
| 10 | return val.to_bytes(length // 8, 'big') |
| 11 | elif typ == 'bytes': |
| 12 | return len(val).to_bytes(4, 'big') + val |
| 13 | elif isinstance(typ, list): |
| 14 | assert len(typ) == 1 |
| 15 | sub = b''.join([serialize(x, typ[0]) for x in val]) |
| 16 | return len(sub).to_bytes(4, 'big') + sub |
| 17 | elif isinstance(typ, type): |
| 18 | sub = b''.join([serialize(getattr(val, k), typ.fields[k]) for k in sorted(typ.fields.keys())]) |
| 19 | return len(sub).to_bytes(4, 'big') + sub |
| 20 | raise Exception("Cannot serialize", val, typ) |
| 21 | |
| 22 | def _deserialize(data, start, typ): |
| 23 | if typ in ('hash32', 'address'): |