Skip to content

refactor: centralize shared character-class predicates#46

Merged
OmarAlJarrah merged 2 commits into
mainfrom
refactor/centralize-grammar-char-classes
Jul 8, 2026
Merged

refactor: centralize shared character-class predicates#46
OmarAlJarrah merged 2 commits into
mainfrom
refactor/centralize-grammar-char-classes

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

What

Five grammar / character-class predicates were each re-derived as 3–5 nearly identical private copies across host/, parser/, serialize/, percent/, scheme/ and idna/:

  • the RFC 3986 unreserved class and its "-._~" literal (×3)
  • the %HH percent-triplet in-bounds hex-pair test (×5) and the octet decode (×2)
  • ASCII-only lowercasing — deliberately locale-invariant, unlike stdlib lowercaseChar() (×3, plus a divergent 4th)
  • the scheme-continuation character class (×3)
  • the all-ASCII string test and the 0x80 boundary constant

Change

Promote each to its canonical home — most to text/CharClasses beside the existing isAsciiHexDigit/hexDigitToInt atoms, and the scheme-tail predicate to the scheme package next to schemeColonIndex. New internal helpers: Char.isUnreserved(), Char.asciiLowercased(), CharSequence.isAllAscii(), hasPercentHexPairAt(), percentByteAt(), and isSchemeContinuationChar().

Every copy was confirmed identical before replacing, so the security-sensitive index + 2 < length bound on the percent-triplet check now has a single definition.

The URL parser's scheme-buffer lowercasing is also converged from the Unicode-aware stdlib lowercaseChar() to the shared ASCII form — both call sites are already guarded to ASCII, so output is unchanged and the last inconsistency is removed.

Safety

Pure refactor — no behavior change. All tests and conformance suites pass unmodified; public API unchanged (apiCheck passes with no apiDump). Verified on the JVM gate and a Kotlin/Native macosArm64 compile. CharClasses gains a @file:Suppress("TooManyFunctions") — expected for the shared char-class utility file.


Stacked on #45.

@OmarAlJarrah OmarAlJarrah force-pushed the refactor/centralize-codepoint-primitives branch from 256c6b6 to 0f71fdd Compare July 8, 2026 10:03
@OmarAlJarrah OmarAlJarrah changed the base branch from refactor/centralize-codepoint-primitives to main July 8, 2026 10:06
…s and scheme

Five grammar / character-class predicates were each re-derived as 3-5 nearly
identical private copies scattered across host/, parser/, serialize/, percent/,
scheme/ and idna/:

  - the RFC 3986 `unreserved` class and its "-._~" literal
  - the "%HH" percent-triplet in-bounds hex-pair test and the octet decode
  - ASCII-only lowercasing (deliberately locale-invariant, unlike the stdlib
    lowercaseChar())
  - the scheme-continuation character class
  - the all-ASCII string test and the 0x80 boundary constant

Promote each to its canonical home: most to text/CharClasses, beside the
existing isAsciiHexDigit / hexDigitToInt atoms, and the scheme-tail predicate
to the scheme package next to schemeColonIndex. Every copy was confirmed
identical before replacing, so the security-sensitive `index + 2 < length`
bound on the percent-triplet check now has a single definition.

While here, converge the URL parser's scheme-buffer lowercasing from the
Unicode-aware stdlib lowercaseChar() to the shared ASCII form; both call sites
are already guarded to ASCII characters, so the output is unchanged and the
inconsistency is removed.

Pure refactor: no behavior change, all tests and conformance suites pass
unmodified, public API unchanged.
@OmarAlJarrah OmarAlJarrah force-pushed the refactor/centralize-grammar-char-classes branch from 5f30ed1 to 4037494 Compare July 8, 2026 10:08
The centralized percentByteAt dropped the misuse guard the previous
PercentCodec.tripletByte carried. Restore it as a require on the two
decoded nibbles: hexDigitToInt already runs, so validating its results
is free, and a caller that reaches percentByteAt without the
hasPercentHexPairAt check now fails loudly instead of composing a garbage
octet from a -1 nibble. No behavior change on verified input.
@OmarAlJarrah OmarAlJarrah merged commit 01b9ff4 into main Jul 8, 2026
10 checks passed
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