1,540 bytes · the Python implementation · view raw
from typing import Optional
def parse_ipv4(text: str) -> int:
"""The address as an unsigned 32-bit number. Only the strict dotted quad is accepted. The C library's inet_aton also reads "010.1.1.1" as octal 8.1.1.1, "0x7f.1" as hex and "127.1" as 127.0.0.1; a validator that agrees with one reader and a socket library that agrees with the other is how an allow-list gets bypassed, so all of those are refused. """
value = ipv4_value(text)
if value isNone:
raise ValueError('"%s" is not a dotted-quad IPv4 address' % (text,))
return value
# Exported for is_ipv4 and for capabilities that parse IPv4 text without# wanting an error; not part of the group's contract.def ipv4_value(text: object) -> Optional[int]:
"""The address as a number, or None when the text is not a strict dotted quad."""ifnot isinstance(text, str):
returnNone
parts = text.split(".")
if len(parts) != 4:
returnNone
value = 0for part in parts:
if len(part) < 1or len(part) > 3:
returnNone# "0" <= ch <= "9" rather than isdigit(), which accepts other scripts' digits.for ch in part:
ifnot ("0" <= ch <= "9"):
returnNone# A leading zero is where octal readers and decimal readers part company.if len(part) > 1and part[0] == "0":
returnNone
octet = int(part)
if octet > 255:
returnNone
value = value * 256 + octet
return value