Skip to content

Public API for third-party / custom projections #242

Closed

Description

@trasch

Context

The projection-genericity effort (#239, #240, #241) made projections pluggable internally: ProjectionDefinition (strategy) + ProjectionRegistry map each Projection enum case to its transform math, all below the public API surface. During that work we decided explicitly not to expose the protocol publicly ("Keep internal" decision, made after reviewing the trade-offs).

What this issue would add

An option for users of the library to register custom projections (e.g. a local grid CRS or a projection the library hasn't shipped) without forking:

  • A public protocol (or struct-based descriptor — probably preferable; public protocols are sticky API commitments, see Swift API design guidelines) exposing:
    • forward/inverse relative to the EPSG:4326 pivot
    • validExtent / worldBoundingBox metadata (would need a proper struct, not the current tuple in the internal protocol)
    • kind: ProjectionKind capability classification
  • A registration API (dictionary-backed lookup replacing/customizing the current eager dictionary in ProjectionRegistry)
  • Likely also a way for custom SRIDs to appear as Projection values — which conflicts with the current closed enum: Int design (would need a raw-value-backed case or a restructure)

Considerations / prior decisions

  • The current internal-first design was deliberate: nothing in shipping projections requires a public API, and pre-registry phases pinned semantics (noSRID verbatim copy, pivot routing) that a public seam would have to preserve
  • .swiftformat/style conventions and strict concurrency apply to any public surface
  • If pursued, design the descriptor now while the internal protocol is still small; retrofitting is more expensive

Related

Activity

  1. trasch commented on Sep 15, 2026

    @trasch
    ContributorAuthor

    Implemented in PR #247 (stacked on #245), per the agreed revised scope:

    • Projection becomes a struct with SRID identity (emoji-breaking for pattern matching; constant names unchanged so dot-shorthand survives). Codable keeps the SRID wire format.
    • Custom registration API: Projection.register(CustomProjection) — value-type descriptor with @Sendable forward/inverse closures relative to the EPSG:4326 (WGS84) pivot (documented as the datum-transformation seam for Support CRSs on other datums (NAD27, OSGB, CH1903+, ...) #243), public struct ProjectionExtent replacing the internal tuple.
    • Add-only by design (per review): no unregister/deactivate; built-ins permanently registered and always enabled. Family toggles / opt-in enablement were explicitly dropped — performance-neutral and correctness-degrading; compile-time trimming (SwiftPM traits) noted as the alternative if binary size ever matters.
    • Performance motivation discovered en route (release benchmarks + parallel test run): per-access registry reads contended catastrophically under Swift Testing's parallelism; the definition-capture design takes the full projected(to:) path to ~1.7× the direct-math baseline, with registry access confined to cold lookups.

    Closes #242 once #247 merges.

  2. trasch commented on Sep 15, 2026

    @trasch
    ContributorAuthor

    Implemented in #250 (consolidation of the reviewed chain; closes #242 on merge).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions