-
Notifications
You must be signed in to change notification settings - Fork 6
/
helper.py
executable file
·66 lines (53 loc) · 1.67 KB
/
helper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import io
from typing import Any, BinaryIO
def hexstr_to_bytes(input_str: str) -> bytes:
"""
Converts a hex string into bytes, removing the 0x if it's present.
"""
if input_str.startswith("0x") or input_str.startswith("0X"):
return bytes.fromhex(input_str[2:])
return bytes.fromhex(input_str)
def make_sized_bytes(size: int):
"""
Create a streamable type that subclasses "bytes" but requires instances
to be a certain, fixed size.
"""
name = "bytes%d" % size
def __new__(cls, v):
v = bytes(v)
if not isinstance(v, bytes) or len(v) != size:
raise ValueError("bad %s initializer %s" % (name, v))
return bytes.__new__(cls, v) # type: ignore
@classmethod # type: ignore
def parse(cls, f: BinaryIO) -> Any:
b = f.read(size)
assert len(b) == size
return cls(b)
def stream(self, f):
f.write(self)
@classmethod # type: ignore
def from_bytes(cls: Any, blob: bytes) -> Any:
# pylint: disable=no-member
f = io.BytesIO(blob)
result = cls.parse(f)
assert f.read() == b""
return result
def __bytes__(self: Any) -> bytes:
f = io.BytesIO()
self.stream(f)
return bytes(f.getvalue())
def __str__(self):
return self.hex()
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, str(self))
namespace = dict(
__new__=__new__,
parse=parse,
stream=stream,
from_bytes=from_bytes,
__bytes__=__bytes__,
__str__=__str__,
__repr__=__repr__,
)
return type(name, (bytes,), namespace)
bytes32 = make_sized_bytes(32)