Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/pyvex/utils.py: 72%

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

40 statements  

1import struct 

2from typing import Any, Callable, Dict, Tuple 

3 

4try: 

5 import _md5 as md5lib 

6except ImportError: 

7 import hashlib as md5lib 

8 

9 

10md5_unpacker = struct.Struct("4I") 

11 

12 

13def stable_hash(t: Tuple) -> int: 

14 cnt = _dump_tuple(t) 

15 hd = md5lib.md5(cnt).digest() 

16 return md5_unpacker.unpack(hd)[0] # 32 bits 

17 

18 

19def _dump_tuple(t: Tuple) -> bytes: 

20 cnt = b"" 

21 for item in t: 

22 if item is not None: 

23 type_ = type(item) 

24 if type_ in _DUMP_BY_TYPE: 

25 cnt += _DUMP_BY_TYPE[type_](item) 

26 else: 

27 cnt += struct.pack("<Q", hash(item) & 0xFFFF_FFFF_FFFF_FFFF) 

28 cnt += b"\xf0" 

29 return cnt 

30 

31 

32def _dump_str(t: str) -> bytes: 

33 return t.encode("ascii") 

34 

35 

36def _dump_int(t: int) -> bytes: 

37 prefix = b"" if t >= 0 else b"-" 

38 t = abs(t) 

39 if t <= 0xFFFF: 

40 return prefix + struct.pack("<H", t) 

41 elif t <= 0xFFFF_FFFF: 

42 return prefix + struct.pack("<I", t) 

43 elif t <= 0xFFFF_FFFF_FFFF_FFFF: 

44 return prefix + struct.pack("<Q", t) 

45 else: 

46 cnt = b"" 

47 while t > 0: 

48 cnt += _dump_int(t & 0xFFFF_FFFF_FFFF_FFFF) 

49 t >>= 64 

50 return prefix + cnt 

51 

52 

53def _dump_type(t: type) -> bytes: 

54 return t.__name__.encode("ascii") 

55 

56 

57_DUMP_BY_TYPE: Dict[type, Callable[[Any], bytes]] = { 

58 tuple: _dump_tuple, 

59 str: _dump_str, 

60 int: _dump_int, 

61 type: _dump_type, 

62}