locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
75 lines (74 loc) • 2.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.inet_pton = inet_pton;
function inet_pton(a) {
// discuss at: https://locutus.io/php/inet_pton/
// parity verified: PHP 8.3
// original by: Theriault (https://github.com/Theriault)
// improved by: alromh87 and JamieSlome
// example 1: inet_pton('::')
// returns 1: '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
// example 2: inet_pton('127.0.0.1')
// returns 2: '\x7F\x00\x00\x01'
const f = String.fromCharCode;
// IPv4
const ipv4Match = a.match(/^(?:\d{1,3}(?:\.|$)){4}/);
if (ipv4Match) {
const octets = ipv4Match[0]
.split('.')
.slice(0, 4)
.map((part) => Number.parseInt(part, 10));
const [a0, a1, a2, a3] = octets;
if (a0 === undefined ||
a1 === undefined ||
a2 === undefined ||
a3 === undefined ||
octets.some((octet) => Number.isNaN(octet) || octet < 0 || octet > 255)) {
return false;
}
const packed = f(a0, a1, a2, a3);
// Return if 4 bytes, otherwise false.
return packed.length === 4 ? packed : false;
}
// IPv6
if (a.length > 39) {
return false;
}
const segments = a.split('::');
if (segments.length > 2) {
return false;
} // :: can't be used more than once in IPv6.
const reHexDigits = /^[\da-f]{1,4}$/i;
const packedSegments = [];
for (const segment of segments) {
if (segment.length === 0) {
packedSegments.push('');
continue;
}
const hextets = segment.split(':');
let packed = '';
for (const hextetSource of hextets) {
const hextet = hextetSource;
// check if valid hex string up to 4 chars
if (!reHexDigits.test(hextet)) {
return false;
}
const parsedHextet = parseInt(hextet, 16);
// Would be NaN if it was blank, return false.
if (Number.isNaN(parsedHextet)) {
// Invalid IP.
return false;
}
packed += f(parsedHextet >> 8, parsedHextet & 0xff);
}
packedSegments.push(packed);
}
const bytesLength = packedSegments.reduce((total, part) => total + part.length, 0);
if (bytesLength > 16) {
return false;
}
if (segments.length === 1 && bytesLength !== 16) {
return false;
}
return packedSegments.join('\x00'.repeat(16 - bytesLength));
}