Skip to content

feat: IPv6 canonicalization to RFC 5952 (#363)#485

Open
SJrX wants to merge 1 commit into
issue-345-15from
issue-345-16
Open

feat: IPv6 canonicalization to RFC 5952 (#363)#485
SJrX wants to merge 1 commit into
issue-345-15from
issue-345-16

Conversation

@SJrX

@SJrX SJrX commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

Closes #363. Offers a quick-fix to rewrite a non-canonical IPv6 address to its RFC 5952 recommended form — e.g. IPAddressAllow=2001:DB8::12001:db8::1, FE80:0:0:0:0:0:0:1fe80::1. Behind the experimental flag.

Stacked on #484 (issue-345-15).

Pieces

  • canonicalizeIpv6(addr) (pure, dependency-free): parse to 8 groups, reformat per RFC 5952 §4 — lowercase hex, drop leading zeros, compress the longest zero run to :: (leftmost on ties, only runs of 2+, never a single zero group). Returns null for non-IPv6 input, and (for now) for embedded-IPv4 §5 mixed notation (::ffff:1.2.3.4), which it leaves alone.
  • Combinator.labeledRegions(value): the grammar's explicit Labeled spans (a whole IP address) from the first fully-valid parse. This is where the coloring work pays off — IP addresses are already Labeled(LITERAL) spans, so I can locate them without any IPv6-specific engine markers.
  • Ipv6CanonicalFormInspection (flag-gated): scans labeled spans of grammar-backed options; canonicalizeIpv6 doubles as the filter (null ⇒ not a pure IPv6). Registers a WEAK_WARNING + CanonicalizeIpv6QuickFix for any non-canonical address.

Tests

  • Ipv6Test: canonicalization incl. zero-run/tie/single-zero/all-zeros/idempotence, and null for IPv4/embedded-IPv4/integer/garbage.
  • Ipv6CanonicalFormInspectionTest: e2e weak-warning, the quick-fix rewriting 2001:DB8::12001:db8::1, and nothing when already canonical or the flag is off.

Known limitation

Embedded-IPv4 (::ffff:1.2.3.4, RFC 5952 §5 mixed notation) is intentionally left alone for now — the §5 rules interact with :: compression and deserve their own pass. Pure IPv6 is fully handled.

Closes #363. Refs #467

🤖 Generated with Claude Code

Offers a quick-fix to rewrite a non-canonical IPv6 address to its recommended form.
Behind the experimental flag.

- canonicalizeIpv6 (pure, dependency-free): parses to 8 groups and reformats per RFC
  5952 §4 — lowercase hex, drop leading zeros, compress the longest zero run to "::"
  (leftmost on ties, only for runs of 2+, never a single zero group). Returns null for
  non-IPv6 input and, for now, for embedded-IPv4 (§5 mixed notation) addresses.
- Combinator.labeledRegions(value): the grammar's explicit Labeled spans (e.g. a whole
  IP address) from the first fully-valid parse — lets features act on semantic spans.
- Ipv6CanonicalFormInspection: flag-gated; for grammar-backed options it scans labeled
  spans and registers a WEAK_WARNING + CanonicalizeIpv6QuickFix on any IPv6 that isn't
  already canonical. Reuses the IPV4_ADDR/IPV6_ADDR Labeled(LITERAL) spans we added for
  coloring, so no IPv6-specific engine markers were needed.

Tests: canonicalizer cases incl. zero-run/tie/single-zero/idempotence/non-IPv6; e2e
warning + quick-fix rewriting 2001:DB8::1 -> 2001:db8::1, and nothing when canonical or
the flag is off.

Closes #363. Refs #467

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Test Results

1 157 tests  +9   1 157 ✅ +9   49s ⏱️ +2s
  307 suites +2       0 💤 ±0 
  307 files   +2       0 ❌ ±0 

Results for commit cab658e. ± Comparison against base commit 4f8ac0f.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant