Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyvex/utils.py: 73%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import struct
2from collections.abc import Callable
3from typing import Any
5try:
6 import _md5 as md5lib
7except ImportError:
8 import hashlib as md5lib
11md5_unpacker = struct.Struct("4I")
14def stable_hash(t: tuple) -> int:
15 cnt = _dump_tuple(t)
16 hd = md5lib.md5(cnt).digest()
17 return md5_unpacker.unpack(hd)[0] # 32 bits
20def _dump_tuple(t: tuple) -> bytes:
21 cnt = b""
22 for item in t:
23 if item is not None:
24 type_ = type(item)
25 if type_ in _DUMP_BY_TYPE:
26 cnt += _DUMP_BY_TYPE[type_](item)
27 else:
28 cnt += struct.pack("<Q", hash(item) & 0xFFFF_FFFF_FFFF_FFFF)
29 cnt += b"\xf0"
30 return cnt
33def _dump_str(t: str) -> bytes:
34 return t.encode("ascii")
37def _dump_int(t: int) -> bytes:
38 prefix = b"" if t >= 0 else b"-"
39 t = abs(t)
40 if t <= 0xFFFF:
41 return prefix + struct.pack("<H", t)
42 elif t <= 0xFFFF_FFFF:
43 return prefix + struct.pack("<I", t)
44 elif t <= 0xFFFF_FFFF_FFFF_FFFF:
45 return prefix + struct.pack("<Q", t)
46 else:
47 cnt = b""
48 while t > 0:
49 cnt += _dump_int(t & 0xFFFF_FFFF_FFFF_FFFF)
50 t >>= 64
51 return prefix + cnt
54def _dump_type(t: type) -> bytes:
55 return t.__name__.encode("ascii")
58_DUMP_BY_TYPE: dict[type, Callable[[Any], bytes]] = {
59 tuple: _dump_tuple,
60 str: _dump_str,
61 int: _dump_int,
62 type: _dump_type,
63}