Skip to content

refactor: share Uri/Url decoded-path projection and builder gates#48

Merged
OmarAlJarrah merged 1 commit into
mainfrom
refactor/share-uri-url-internals
Jul 8, 2026
Merged

refactor: share Uri/Url decoded-path projection and builder gates#48
OmarAlJarrah merged 1 commit into
mainfrom
refactor/share-uri-url-internals

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

What

Two verbatim duplications between the deliberately-separate Uri (RFC 3986) and Url (WHATWG) profiles.

  • The decoded-path-segments projection — a when over the shared UrlPath that percent-decodes each segment — was byte-identical in Uri.computeDecodedPathSegments and Url.pathSegments.
  • Each builder stated its composability rules twice: throwing requires for build() and a boolean && chain for buildOrNull(). A rule change had to be mirrored by hand or the two would silently diverge.

Change

  • Move the projection to a decodedSegments helper in UrlPath, beside the existing shared fileNameOf / toUriPathString / appendPathSegments projections, following the same decode-lambda convention that keeps UrlPath percent-codec-free. Each caller's caching is preserved (Uri memoizes via by lazy; Url recomputes per access — a pre-existing, out-of-scope asymmetry).
  • Replace each builder's two rule-lists with one ordered, private, per-profile composabilityError(): String?. build() throws IllegalArgumentException with the first failure's message (identical to the prior require); buildOrNull() returns null when it's non-null. The two prior forms were verified exactly equivalent first — no pre-existing drift.

Safety

Per-profile throughout — no shared supertype, no cross-profile coupling (the two-profile design is intentional). Pure refactor: exception types, messages, and check order are unchanged; buildOrNull() returns null in exactly the same cases. Public API unchanged (apiCheck passes with no apiDump). Verified on the JVM gate + a Kotlin/Native macosArm64 compile.


Stacked on #47.

@OmarAlJarrah OmarAlJarrah force-pushed the refactor/consolidate-serialization branch from 37d0b91 to 7e0814c Compare July 8, 2026 10:27
Base automatically changed from refactor/consolidate-serialization to main July 8, 2026 10:28
…lder gates

Two verbatim duplications between the deliberately-separate Uri and Url
profiles, factored without coupling the two:

  - The decoded-path-segments projection (a `when` over the shared UrlPath that
    percent-decodes each segment) was byte-identical in
    Uri.computeDecodedPathSegments and Url.pathSegments. Move it to a
    `decodedSegments` helper in UrlPath, alongside the existing shared
    fileNameOf / toUriPathString / appendPathSegments projections, following the
    same decode-lambda convention that keeps UrlPath percent-codec-free. Each
    caller's caching is unchanged (Uri still memoizes via `by lazy`, Url still
    recomputes per access).
  - Each builder stated its composability rules twice — throwing `require`s for
    build() and a boolean chain for buildOrNull() — so a rule change had to be
    mirrored by hand or the two would silently diverge. Replace each with one
    ordered, private, per-profile `composabilityError(): String?`; build()
    throws IllegalArgumentException with the first failure's message (identical
    to the prior `require`), buildOrNull() returns null when it is non-null. The
    two forms were verified exactly equivalent beforehand.

Per-profile throughout: no shared supertype, no cross-profile coupling. Pure
refactor, public API unchanged.
@OmarAlJarrah OmarAlJarrah force-pushed the refactor/share-uri-url-internals branch from 1b431d8 to fc6fd17 Compare July 8, 2026 10:32
@OmarAlJarrah OmarAlJarrah merged commit 1bba719 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