| 59 | // compressed literal: "127.0.0.1::1" would parse, land 0x7f00 in the leading |
| 60 | // word where no prefix or mask matches it, and be classified public. |
| 61 | const parseIpv6Groups = (text: string, allowTrailingQuad: boolean): number[] | null => { |
| 62 | if (text === "") return []; |
| 63 | const parts = text.split(":"); |
| 64 | const groups: number[] = []; |
| 65 | for (const [index, part] of parts.entries()) { |
| 66 | // A trailing dotted quad is the only place IPv4 syntax is legal. |
| 67 | if (index === parts.length - 1 && part.includes(".")) { |
| 68 | if (!allowTrailingQuad) return null; |
| 69 | const dotted = parseIpv4(part); |
| 70 | if (!dotted) return null; |
| 71 | groups.push((dotted[0] << 8) | dotted[1], (dotted[2] << 8) | dotted[3]); |
| 72 | continue; |
| 73 | } |
| 74 | if (!/^[0-9a-f]{1,4}$/.test(part)) return null; |
| 75 | groups.push(Number.parseInt(part, 16)); |
| 76 | } |
| 77 | return groups; |
| 78 | }; |
| 79 | |
| 80 | // Expands an IPv6 literal into its eight 16-bit words, resolving the "::" |
| 81 | // run to its true position. Classification has to work from the real words: |