-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathhexbytes.py
More file actions
43 lines (33 loc) · 1.12 KB
/
Copy pathhexbytes.py
File metadata and controls
43 lines (33 loc) · 1.12 KB
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
from __future__ import annotations
import re
_HEX_RE = re.compile(r"[0-9a-fA-F]")
def parse_hex_input(s: str) -> bytes:
"""Parse a variety of common hex/byte literal formats into raw bytes.
Accepts:
- Inline escaped: \x90\x90\x48...
- C-style: 0x90,0x90,0x48 or 0x90 0x90 0x48
- Raw hex: 909048...
- With whitespace, commas, newlines
"""
if not s:
return b""
s = s.strip()
# Inline \x.. sequences
if "\\x" in s:
pairs = re.findall(r"\\x([0-9a-fA-F]{2})", s)
if not pairs:
raise ValueError("No valid \\xHH sequences found")
return bytes(int(p, 16) for p in pairs)
# Remove 0x prefixes and non-hex separators
cleaned = re.sub(r"0x", "", s, flags=re.IGNORECASE)
cleaned = re.sub(r"[^0-9a-fA-F]", "", cleaned)
if not cleaned:
return b""
if len(cleaned) % 2 != 0:
raise ValueError("Odd-length hex string after cleaning")
try:
return bytes.fromhex(cleaned)
except ValueError as e:
raise ValueError(f"Invalid hex input: {e}")
def count_nulls(b: bytes) -> int:
return sum(1 for x in b if x == 0)