Skip to content
Documentation menu
docs / ios-reference · raw .md

MapMapKit (iOS) reference

Generated from the published MapMapKit 0.8.0 sources (github.com/Mapmapai/mapmap-ios, tag 0.8.0) by website/scripts/sdk-reference-native.mjs. Do not edit by hand: change the doc comments in the SDK, or the examples in website/content/sdk-reference/ios.examples.md, and regenerate.

Every public declaration of the Swift package at release 0.8.0: the MapMapKit, MapMapValhalla and MapMapCarPlay products. The guide is iOS (Swift) in SDKs & installation, with Mobile maps with MapLibre Native for the map itself.

swift
// Package.swift
.package(url: "https://github.com/Mapmapai/mapmap-ios.git", exact: "0.8.0")

Other SDK references: @mapmap/maps, @mapmap/points, @mapmap/core, @mapmap/tile, @mapmap/react-native, @mapmap/voice, ai.mapmap:core.

236 public declarations across 3 modules: 50 written by hand, 186 in the generated Rust bindings.

How to read this page

Each entry gives the declaration as written in the release source (in Kotlin without identifier backticks or the kotlin. package prefix), its doc comment, and its public members. The Default column shows a value only where the source writes one (an initialiser, a parameter's default, or a doc comment that states it); otherwise it is blank. Types and classes written by hand carry a minimal example. The generated bindings are the Rust core's types as UniFFI exposes them; their descriptions are the Rust doc comments.

Contents

MapMapKit

Classes (MapMapKit)

CoreLocationProvider, HTTPChannelFetcher, URLSessionProbeUploader, VoiceGuidance

CoreLocationProvider

Class · Sources/MapMapKit/Navigation/CoreLocationProvider.swift

swift
public final class CoreLocationProvider: LocationProvider

Live LocationProvider on Core Location.

The SDK's Info.plist declares no usage strings. Apps must add NSLocationWhenInUseUsageDescription (and NSLocationAlwaysAndWhenInUseUsageDescription plus the location background mode for background guidance) and obtain authorisation before the stream is consumed, see ios/README.md ("Location authorisation"). If authorisation is denied while streaming, the stream finishes by throwing CLError.denied.

Samples map platform sentinels to nil: negative horizontalAccuracy (invalid fix channels), negative speed and negative course are all reported as absent rather than passed through.

PropertyTypeDefaultDescription
var locationsAsyncThrowingStream<LocationSample, Error>

Initialisers and methods

  • public init(configuration: Configuration = Configuration())

Nested: CoreLocationProvider.Configuration.

Example

swift
import MapMapKit

let gps = CoreLocationProvider(configuration: .init(allowsBackgroundLocationUpdates: true))
for try await fix in gps.locations {
    print(fix.lat, fix.lon, fix.horizontalAccuracyM ?? -1)
}

HTTPChannelFetcher

Class · Sources/MapMapKit/Territory/ChannelSource.swift

swift
public final class HTTPChannelFetcher: LayerFetcher, @unchecked Sendable

A blocking HTTPS LayerFetcher for a ChannelSource, on URLSession. TerritoryStore calls it off the cooperative pool.

apiKey is sent as Authorization: Bearer <apiKey> (the hosted gateway meters layer downloads against the key's allowance); nil for an open mirror. cancel is polled while a request is in flight, so a tripped token aborts the transfer, not only the next one. configuration defaults to an ephemeral session (pass your own for a proxy or a test URLProtocol).

PropertyTypeDefaultDescription
let sourceChannelSource
var bytesReceivedInt64Total bytes received so far.
var lastFailedStatusInt?HTTP status of the last failed request: 401/403 auth, 402 allowance, 404 not found.

Initialisers and methods

  • public init(source: ChannelSource, apiKey: String? = nil, cancel: CancelToken? = nil, onBytes: (@Sendable (Int64) -> Void)? = nil, configuration: URLSessionConfiguration? = nil)
  • public func fetchIndex() throws -> SignedChannelIndex: GET the signed index and its signature, exact bytes.
  • public func fetch(relPath: String, expectedBlake3: String, destPath: String) throws

Example

swift
import MapMapKit

// The fetcher TerritoryStore.sync(territoryId:source:apiKey:) builds for you; use it directly
// when you drive installFromChannel or checkForUpdate yourself.
let fetcher = HTTPChannelFetcher(source: .gateway(), apiKey: "snk_…")
let index = try fetcher.fetchIndex()
print(index.json.count, fetcher.bytesReceived)

URLSessionProbeUploader

Class · Sources/MapMapKit/Navigation/ProbeContribution.swift

swift
public final class URLSessionProbeUploader: ProbeUploader, @unchecked Sendable

Default ProbeUploader: POSTs each body to {baseURL}/v1/probe with a bearer key via URLSession. Transient failures (transport or 5xx) are retried with bounded backoff; permanent ones (400/403/501) are dropped. No third-party dependency.

Initialisers and methods

  • public init(baseURL: String, apiKey: String, session: URLSession = .shared, maxAttempts: Int = 4, backoff: @escaping @Sendable (Int) -> TimeInterval = { TimeInterval($0) }, onResult: @escaping @Sendable (ProbeUploadOutcome) -> Void = { _ in }): - Parameters: - baseURL: gateway origin, e.g. https://api.mapmap.ai (a trailing slash is tolerated). - maxAttempts: total tries including the first. - backoff: attempt number → delay before the next try.
  • public func enqueue(_ body: String)

Example

swift
import MapMapKit

// Opt-in aggregate probe upload (POST /v1/probe), retried with backoff.
let uploader = URLSessionProbeUploader(baseURL: "https://api.mapmap.ai", apiKey: "snk_…") { outcome in
    print("probe upload:", outcome)
}
let routeJson = "{}" // a Valhalla route response
let engine = NavigationEngine(routeResponseJson: routeJson)
let states = contributingProbe(
    await engine.navigate(provider: CoreLocationProvider()),
    config: ProbeConfig(enabled: true),
    uploader: uploader
)
for try await state in states { if state.isArrived { break } }

VoiceGuidance

Class · Sources/MapMapKit/Navigation/VoiceGuidance.swift

swift
public final class VoiceGuidance: NSObject, AVSpeechSynthesizerDelegate

Spoken turn-by-turn guidance over AVSpeechSynthesizer (offline, the platform voices synthesise on device).

Feed every NavigationState (or raw GuidanceUpdate) from NavigationEngine/navigate(provider:):

swift let voice = VoiceGuidance() for try await state in await engine.navigate(provider: provider) { voice.handle(state) render(state) }

The core schedules each spoken prompt by its trigger distance and repeats it on every update until it is superseded, so the speaking rule is: announce each utteranceId exactly once, the first time it appears. Severity maps to prosody and earcons via VoiceProsody; critical prompts stop pending speech. Off-route plays the warning earcon once per episode. Observe isSpeaking / onSpeakingChanged to reflect live speaking state in UI (e.g. a pulsing voice icon). On iOS the audio session ducks other audio around announcements (.duckOthers + .voicePrompt), so music dims rather than stops, and is deactivated again once the last utterance finishes, so music comes back to full volume instead of staying ducked forever.

PropertyTypeDefaultDescription
var isSpeakingBoolWhether an utterance is currently being spoken or queued. Mirrors the transitions delivered to onSpeakingChanged.
var onSpeakingChanged((Bool) -> Void)?Called on every speaking-state transition: true when the first utterance of a burst starts, false once the last one finishes, is cancelled or stop() is called. May be invoked on an arbitrary queue (the synthesiser's delegate queue), hop to the main actor before touching UI.
var mutedBoolfalseWhether announcements are muted. Toggle freely mid-drive; muting also stops anything mid-utterance.
var volumeFloat1.0Announcement volume, 0–1 (applied to speech and earcons).

Initialisers and methods

  • public init(language: String? = nil, baseRate: Float = AVSpeechUtteranceDefaultSpeechRate): - Parameters: - language: BCP 47 tag for the voice, e.g. en-GB. nil keeps the device default voice. - baseRate: base AVSpeechUtterance rate (platform default when omitted).
  • public func handle(_ update: GuidanceUpdate): Consume one guidance update. Cheap; call it for every emission of NavigationEngine/navigate(provider:).
  • public func handle(_ state: NavigationState): Convenience overload for NavigationEngine/navigate(provider:) emissions.
  • public func stop(): Stop speech and release the earcon player. Deactivates the audio session (un-ducking whatever else plays) when anything was live.
  • public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance)
  • public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance)

Example

swift
import MapMapKit

let voice = VoiceGuidance(language: "en-GB")
voice.volume = 0.8
voice.onSpeakingChanged = { speaking in print("speaking:", speaking) }
// For every emission of NavigationEngine.navigate(provider:):
// voice.handle(state.update)
voice.muted = true

Actors (MapMapKit)

NavigationEngine, TerritoryStore

Actor · Sources/MapMapKit/Navigation/NavigationEngine.swift

swift
public actor NavigationEngine

Turn-by-turn guidance over one computed route.

The Rust core's GuidanceSession (Ferrostar-based) is the navigation state machine; this engine owns its lifecycle and adapts it to Swift concurrency: stream LocationSamples in from any LocationProvider, receive NavigationStates out. The stream completes after arrived. An engine is bound to a single route, on offRoute, compute a new route and build a new engine (see NavigationState/needsReroute).

Ferrostar UI note: the Stadia Maps Ferrostar iOS packages (https://github.com/stadiamaps/ferrostar, SwiftPM products FerrostarCore, FerrostarMapLibreUI, FerrostarSwiftUI, FerrostarCarPlayUI) can render on top of this state, but our GuidanceSession remains the state machine, see ios/README.md, "Ferrostar boundary".

Initialisers and methods

  • public init(routeResponseJson: String, config: GuidanceConfig = GuidanceConfig())
  • public init(route: RouteResult, config: GuidanceConfig = GuidanceConfig()): Build an engine from a route computed by OfflineRouting/route(router:waypoints:costing:adr:).
  • public func totalSteps() throws -> UInt32: Total number of steps in the route (including arrival), for progress UIs. Opens a short-lived native session. - Throws: NavCoreError if the route response cannot start a session (e.g. malformed JSON).
  • public func navigate(provider: some LocationProvider) -> AsyncThrowingStream< NavigationState, Error >: Run guidance: feed every fix from provider into a fresh native session and emit the resulting states. Each call starts a new session at the first route step; a previous run on the same engine is stopped first. The stream completes after arrival, or fails with NavCoreError if the route response cannot start a session, or with the provider's error if the fix stream fails.
  • public func advanceToNextStep() throws: Manually advance to the next step, the tunnel/no-GNSS escape hatch (Ferrostar exposes this on its navigator; the core forwards it). Ignored before the first fix of the active run, mirroring the Android SDK.
  • public func stop(): Stop the active run, if any: the stream finishes without error and the native session is released.

Example

swift
import MapMapKit

// A Valhalla route response (hosted /route, or OfflineRouting.route on the device).
let routeJson: String = try String(contentsOf: Bundle.main.url(forResource: "route", withExtension: "json")!)
let engine = NavigationEngine(routeResponseJson: routeJson)
let voice = VoiceGuidance(language: "en-GB")
for try await state in await engine.navigate(provider: CoreLocationProvider()) {
    voice.handle(state.update)
    if state.isArrived { break }
    if state.needsReroute { /* request a new route and build a new engine */ }
}

TerritoryStore

Actor · Sources/MapMapKit/Territory/TerritoryStore.swift

swift
public actor TerritoryStore

Actor-isolated store of signed offline territory packages.

Wraps the Rust TerritoryManager: every package is ed25519-signature and BLAKE3-layer-hash verified before promotion, and nothing is trusted until verification passes. Verification is fail-closed, a package that does not verify is never promoted and leaves nothing on disk.

All methods are async by actor isolation; the disk-heavy calls (installs read whole archives) additionally hop onto a detached utility task so they never occupy a cooperative-pool thread for the duration of an install.

territories caches the installed set; it refreshes after every mutating call and on refresh(). Observe changes with territoryUpdates().

Installs are cancellable. The cancel: overloads take a CancelToken (from the core) that can be tripped from any thread, and they also trip it when the calling Swift Task is cancelled, so task.cancel() works the way callers expect. A cancelled install returns InstallOutcome.cancelled / UpdateOutcome.cancelled rather than throwing: nothing was installed, staging is removed, the previous version is untouched. Cancelling after completion changes nothing.

Custom regions (region- ids, cut by POST /v1/jobs/territory) are signed by a separate region key. Pass its public half as regionKeyHex (TerritoryKeys/hostedRegionKeyHex for the hosted gateway) to accept them; the core then verifies region- ids against that key only and every other id against the factory key only. Without it every region- package is refused as a bad signature.

PropertyTypeDefaultDescription
var territories[TerritoryInfo][]The installed territories as of the last refresh or mutation.
var acceptsCustomRegionsBoolWhether this store was given a region key, and so can install custom regions.

Initialisers and methods

  • public init(rootDir: URL, verifyingKeyHex: String, regionKeyHex: String? = nil): - Parameters: - rootDir: directory the store owns; created on first use. - verifyingKeyHex: the factory signing key's public half, 64 hex characters (sn_package::VerifyingKey::to_hex). Baked into the app at build time, treat it like a pin. - regionKeyHex: the region signing key's public half, 64 hex characters, or nil to refuse custom regions. Pinned like the factory key; never read from the network.
  • public func refresh() async throws -> [TerritoryInfo]: Re-read the installed set from disk, cache and broadcast it.
  • public func install(snpkg: URL) async throws -> TerritoryInfo: Install a packed .snpkg archive. Verify-then-promote: a package that fails verification leaves no trace on disk. - Throws: NavCoreError/Verification(message:) if the signature or any layer hash does not verify.
  • public func install(snpkg: URL, cancel: CancelToken) async throws -> InstallOutcome: install(snpkg:) with a cancellation handle. The core polls cancel between archive entries, before verification and before promotion; a tripped token (or a cancelled calling task) yields .cancelled with staging removed and nothing installed.
  • public func installDirectory(_ packageDir: URL) async throws -> TerritoryInfo: Install an unpacked package directory (same verification rules).
  • public func installDirectory(_ packageDir: URL, cancel: CancelToken) async throws -> InstallOutcome: installDirectory(_:) with a cancellation handle; see install(snpkg:cancel:).
  • public func installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: [MapLayerKind] = [], cancel: CancelToken = CancelToken()) async throws -> ChannelInstallOutcome: Install territoryId from its channel: the first-install counterpart of applyUpdate(territoryId:manifestJson:manifestSigBase64:fetcher:). indexJson / indexSigBase64 are the exact served bytes of the channel index and its detached signature; the channel's latest version is installed, fetching only the layers not in omit. Nothing is trusted but the pinned keys: the index signature, the manifest signature and every layer hash are checked, and the assembled package goes through the full verification pass before it is promoted. Interrupted installs resume. A tripped cancel (or a cancelled calling task) yields .cancelled with nothing installed. - Throws: NavCoreError/Verification(message:) if a signature or hash does not verify, including a region- id on a store without a region key.
  • public func sync(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: [MapLayerKind] = [], cancel: CancelToken = CancelToken()) async throws -> ChannelSync: Bring territoryId to the channel's latest version, whichever way that takes: a first install from the channel when it is not installed, a signed differential update when an older version is, nothing when it is already current. Updates go through checkForUpdate(territoryId:indexJson:indexSigBase64:fetcher:), so a channel can never move an installed territory backwards.
  • public func sync(territoryId: String, source: ChannelSource, apiKey: String? = nil, omit: [MapLayerKind] = [], cancel: CancelToken = CancelToken(), onBytes: (@Sendable (Int64) -> Void)? = nil) async throws -> ChannelSync: sync(territoryId:indexJson:indexSigBase64:fetcher:omit:cancel:) over HTTPS: fetch the signed index from source and every layer relative to it with an HTTPChannelFetcher. cancel also stops a transfer in progress.
  • public func installCustomRegion(territoryId: String, indexURL: URL, indexSigURL: URL, apiKey: String? = nil, omit: [MapLayerKind] = [], cancel: CancelToken = CancelToken(), onBytes: (@Sendable (Int64) -> Void)? = nil) async throws -> ChannelSync: Install, or update, a custom region from the territory_id, index_url and index_sig_url of a POST /v1/jobs/territory result. A re-cut of the same area after the country is republished is the same id at a newer version, so calling this again is the update. - Throws: ChannelSourceError/noRegionKey if this store has no region key; ChannelSourceError for a malformed id or URL.
  • public func verify(territoryId: String) async throws -> TerritoryInfo: Re-verify an installed territory from disk: the manifest signature (against the key its id is partitioned to), the hash of every layer it holds and the absence of every layer it omitted. The on-demand integrity check for after a restore or a crash. - Throws: NavCoreError/Verification(message:) when the install must be repaired or reinstalled.
  • public func setActive(_ territoryId: String) async throws: Mark territoryId active; persisted atomically by the core.
  • public func active() async throws -> String?: The active territory id, if one is set and still installed.
  • public func activeTerritory() async throws -> TerritoryInfo?: The active territory's full info, if any.
  • public func layerPath(territoryId: String, kind: MapLayerKind) async throws -> URL: Absolute path of one layer of an installed territory, e.g. MapLayerKind/valhallaTiles for the on-device router, MapLayerKind/pmtiles for MapLibre.
  • public func territoryStyle(territoryId: String, theme: StyleTheme = .light) async throws -> String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK's buildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via a pmtiles://<absolute path> URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly.
  • public func openSearch(territoryId: String) async throws -> TerritorySearch: Open the installed territory's bundled geocode index for fully offline on-device search. The returned handle holds the index open (mmap-backed), create it once per territory and reuse it: swift let search = try await store.openSearch(territoryId: "uk") let places = try search.search( query: "watford gap", near: nil, limit: 10)
  • public func remove(_ territoryId: String) async throws: Remove an installed territory (clears the active marker if needed).
  • public func planUpdate(newManifestJson: String) async throws -> UpdatePlan: Plan a differential update against a newly served (signed) manifest JSON: which layers must be downloaded, and how many bytes.
  • public func checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher) async throws -> AvailableUpdate?: Check the signed channel index for an update to an installed territory. indexJson must be the exact bytes served as index.json and indexSigBase64 the content of index.json.sig; the remote manifest is fetched and verified through fetcher (the app's download transport, URLSession, an air-gapped mirror, …, the core decides what to fetch and cryptographically verifies everything itself). Returns nil when the device is already on the channel's latest version or the channel does not list the territory.
  • public func applyUpdate(territoryId: String, manifestJson: String, manifestSigBase64: String, fetcher: LayerFetcher) async throws -> UpdateResult: Apply a differential update: stage, fetch only the changed layers through fetcher, verify everything and swap atomically. Any failure leaves the installed territory untouched; the active flag is preserved.
  • public func applyUpdate(territoryId: String, update: AvailableUpdate, fetcher: LayerFetcher) async throws -> UpdateResult: Apply an update discovered by checkForUpdate(territoryId:indexJson:indexSigBase64:fetcher:), passing its manifest and signature through verbatim.
  • public func applyUpdate(territoryId: String, manifestJson: String, manifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken) async throws -> UpdateOutcome: applyUpdate(territoryId:manifestJson:manifestSigBase64:fetcher:) with a cancellation handle. The core polls cancel before every layer download, between archive entries while unpacking, before each hash pass and before promotion; a tripped token (or a cancelled calling task) yields .cancelled. The installed version is untouched and staging removed; layers already fetched and verified stay in the resumable cache, so a later attempt with the same manifest re-fetches only what is missing. The token cannot interrupt fetcher while it is inside a transfer: give the fetcher the same token and have it poll isCancelled() between chunks (or cancel its URLSessionTask). Whatever the fetcher then throws, a tripped token reports .cancelled rather than a transport error.
  • public func applyUpdate(territoryId: String, update: AvailableUpdate, fetcher: LayerFetcher, cancel: CancelToken) async throws -> UpdateOutcome: applyUpdate(territoryId:update:fetcher:) with a cancellation handle; see applyUpdate(territoryId:manifestJson:manifestSigBase64:fetcher:cancel:).
  • public func territoryUpdates() -> AsyncStream<[TerritoryInfo]>: A stream of the installed set: yields the current value immediately, then every subsequent change. Each call returns an independent stream; it finishes when the store is deallocated.

Example

swift
import MapMapKit

let root = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
    .appendingPathComponent("territories")
let store = TerritoryStore(
    rootDir: root,
    verifyingKeyHex: TerritoryKeys.hostedFactoryKeyHex,
    regionKeyHex: TerritoryKeys.hostedRegionKeyHex
)
// First install or update, whichever is needed, from the hosted channel.
let result = try await store.sync(territoryId: "uk", source: .gateway(), apiKey: "snk_…")
try await store.setActive("uk")
let styleJson = try await store.territoryStyle(territoryId: "uk", theme: .dark)
print(result, styleJson.count)

Structs (MapMapKit)

ChannelSource, CoreLocationProvider.Configuration, CorpusFormatError, DriveCorpus, DriveFix, DriveHeader, LocationSample, NavigationCameraInterpolator, NavigationState, ReplayLocationProvider, SignedChannelIndex, SpeechSessionRefCount, VoiceProsody

ChannelSource

Struct · Sources/MapMapKit/Territory/ChannelSource.swift

swift
public struct ChannelSource: Equatable, Sendable

Where a signed territory channel lives over HTTPS: its index, the index's detached signature, and the base every channel-relative layer path (territories/<id>/<version>/...) is resolved against.

Nothing fetched from here is trusted: the core verifies the index signature, the manifest signature and every layer hash against the keys pinned in the TerritoryStore.

PropertyTypeDefaultDescription
let indexURLURL
let indexSigURLURL
let layerBaseURLURLLayer paths are appended to this.
static let defaultGatewayThe hosted gateway.

Initialisers and methods

  • public init(indexURL: URL, indexSigURL: URL, layerBaseURL: URL)
  • public static func gateway(_ base: URL = defaultGateway) -> ChannelSource: A gateway's country channel: GET /territories (the signed index) and GET /territories/index.sig.
  • public static func customRegion(territoryId: String, indexURL: URL, indexSigURL: URL) throws -> ChannelSource: A custom region's own one-territory channel, from the index_url / index_sig_url of a POST /v1/jobs/territory result. The gateway serves the index at <base>/v1/territories/<id>/index.json and the layers under <base>/territories/<id>/..., so the layer base is <base>. Any other .../index.json (a mirror of the region directory, laid out as SN_REGION_DIR/<id>/) resolves layers next to the index. - Throws: ChannelSourceError if territoryId is not a custom-region id or indexURL does not end in index.json.
  • public static func isCustomRegionId(_ territoryId: String) -> Bool: Whether territoryId has the shape the gateway gives custom regions: region- plus 16 lowercase hex characters.

CoreLocationProvider.Configuration

Struct · Sources/MapMapKit/Navigation/CoreLocationProvider.swift

swift
public struct Configuration: Sendable

Configuration forwarded to CLLocationManager.

PropertyTypeDefaultDescription
var desiredAccuracyCLLocationAccuracyDesired accuracy; vehicular guidance wants kCLLocationAccuracyBestForNavigation.
var distanceFilterCLLocationDistanceDistance filter in metres (kCLDistanceFilterNone = every fix).
var activityTypeCLActivityTypeActivity type hint for the platform's fusion.
var allowsBackgroundLocationUpdatesBoolWhether to request background updates (requires the app's location background mode).

Initialisers and methods

  • public init(desiredAccuracy: CLLocationAccuracy = kCLLocationAccuracyBestForNavigation, distanceFilter: CLLocationDistance = kCLDistanceFilterNone, activityType: CLActivityType = .automotiveNavigation, allowsBackgroundLocationUpdates: Bool = false)

CorpusFormatError

Struct · Sources/MapMapKit/Replay/DriveCorpus.swift

swift
public struct CorpusFormatError: Error, Equatable, LocalizedError

A .drive.jsonl document violated the corpus format.

PropertyTypeDefaultDescription
let messageString
var errorDescriptionString?

Initialisers and methods

  • public init(_ message: String)

DriveCorpus

Struct · Sources/MapMapKit/Replay/DriveCorpus.swift

swift
public struct DriveCorpus: Equatable, Sendable

Parser for the .drive.jsonl replay corpus format produced by the workspace's sn-replay crate (see crates/sn-replay/src/corpus.rs).

Line 1 is a JSON header (format_version, name, description, route_fixture, seed, optional generator); every following non-blank line is one GPS fix (t_ms, lat, lon, optional speed_mps, bearing_deg, horizontal_accuracy_m). The Swift parser enforces the same invariants as the Rust one (and the Kotlin one in android/): supported format version, non-empty name, at least one fix, strictly increasing t_ms, and sane coordinate/channel ranges.

PropertyTypeDefaultDescription
static let formatVersionThe corpus format version this parser accepts.
let headerDriveHeader
let fixes[DriveFix]

Initialisers and methods

  • public static func parse(_ jsonl: String) throws -> DriveCorpus: Parse and validate a corpus from JSON-lines text. - Throws: CorpusFormatError describing the first violation, with its 1-based line number where applicable.
  • public static func parse(contentsOf url: URL) throws -> DriveCorpus: Read and parse a corpus file.

DriveFix

Struct · Sources/MapMapKit/Replay/DriveCorpus.swift

swift
public struct DriveFix: Equatable, Sendable

One GPS fix line of a corpus. tMs is milliseconds since drive start.

PropertyTypeDefaultDescription
let tMsInt64
let latDouble
let lonDouble
let speedMpsDouble?
let bearingDegDouble?
let horizontalAccuracyMDouble?

DriveHeader

Struct · Sources/MapMapKit/Replay/DriveCorpus.swift

swift
public struct DriveHeader: Equatable, Sendable

Header line of a .drive.jsonl corpus.

PropertyTypeDefaultDescription
let formatVersionInt
let nameString
let descriptionString
let routeFixtureString
let seedInt64

LocationSample

Struct · Sources/MapMapKit/Navigation/LocationProvider.swift

swift
public struct LocationSample: Equatable, Sendable

One position sample fed into guidance.

PropertyTypeDefaultDescription
var latDoubleLatitude in decimal degrees (WGS84).
var lonDoubleLongitude in decimal degrees (WGS84).
var timestampMsInt64Milliseconds since the Unix epoch.
var speedMpsDouble?Speed over ground in metres per second, when the source reports it.
var bearingDegDouble?Course over ground, degrees clockwise from true north, [0, 360).
var horizontalAccuracyMDouble?Estimated 1-sigma horizontal accuracy in metres. Pass the platform value whenever available, the core uses it to gate step advance and deviation detection.

Initialisers and methods

  • public init(lat: Double, lon: Double, timestampMs: Int64, speedMps: Double? = nil, bearingDeg: Double? = nil, horizontalAccuracyM: Double? = nil)

Struct · Sources/MapMapKit/Navigation/NavigationCameraInterpolator.swift

swift
public struct NavigationCameraInterpolator: Sendable

Turns a ~1 Hz stream of guidance fixes into a value that can be sampled on every display frame, so a follow camera moves continuously instead of stepping once per fix.

Why this type exists

Guidance fixes arrive at roughly 1 Hz (the replay corpora and Core Location both). Driving a map camera straight off them looks jerky in two distinct ways, and only one of them is fixed by easing:

  1. Per-tick easing. Kicking off one animation per fix (MapLibre's easeTo/setCamera(_:withDuration:)) hands the camera a new target while the previous animation is still running. Each new animation restarts from wherever the last one had got to, with its own easing curve, so the velocity resets 1x/second, visible as a pulse.
  2. Two clocks. Animating a map-anchored puck while the camera is itself animating gives the scene two independent clocks that drift against each other. That desync is the "stutters back and forth, worse at low zoom" bug already diagnosed and fixed in the MapMapNav app (see src/screens/guidance/ChaseLayer.tsx, whose fix, camera only, puck as a fixed screen overlay, this iOS work mirrors).

This type addresses (1): the host samples it from a CADisplayLink and applies the result to the map with no animation, so the frame clock is the only clock. (2) is addressed by the host drawing the puck as a fixed overlay at the camera focal point.

There is a third way for this to look wrong, and setRoute(coordinates:) is the answer to it: interpolating in a straight line between two fixes a second apart cuts corners, so through a bend the vehicle drifts off the road and back on. Given the route, the interpolation runs in arc length along it and every position reported is a point of the route.

Presentation lag (deliberate)

state(at:) reports where the vehicle was one fix-interval ago. That lag is what lets it interpolate between two known fixes rather than guess ahead of the newest one, and it is what makes the motion continuous: the sample reaches fix N exactly as fix N+1 lands, and the next segment starts from that same point.

This is not a new trade-off. The approved MapMapNav chase camera has the identical lag by construction, ChaseLayer eases to each fix over a duration equal to the gap since the previous one, so its camera also arrives at fix N as fix N+1 appears. The difference here is only that a frame clock replaces one animation per tick.

Guidance text, distances and ETA are not lagged: they come straight from the engine tick. Only the camera geometry is interpolated.

Clock

The type is clock-agnostic: timestamp is whatever monotonic seconds the host feeds, and state(at:) must be queried on the same clock. Hosts should feed the arrival time of each fix (CACurrentMediaTime()), not the fix's own timestampMs: arrival time is what the extrapolation cap needs to reason about, and it stays correct when a replay runs at a time scale (ReplayLocationProvider(timeScale:)) or when fixes are delivered late.

Pure value type: no UIKit, no MapLibre, no CarPlay, so it builds and is tested on the macOS host path (MAPMAP_HOST_CORE=1 swift test) as well as on iOS.

PropertyTypeDefaultDescription
static let bearingSmoothAlphaDouble0.35Per-fix low-pass factor for the camera bearing (0…1; lower is smoother and laggier). 0.35, taken verbatim from BEARING_SMOOTH_ALPHA in MapMapNav's src/screens/guidance/GuidanceScreen.tsx, where it is the value proven on device: enough damping that a noisy heading or a sharp corner does not whip the map, tight enough that the camera still tracks the corner.
static let standstillSpeedMpsDouble0.5Below this speed the reported course is noise, so the smoothed bearing is frozen rather than followed. 0.5 m/s is the same standstill threshold MapMapNav uses to decide a fix is not moving (speedMps > 0.5 in state/guidance/routeProgress.ts and state/guidance/fasterRoute.ts). A stationary vehicle's course wanders over the whole compass; following it spins the map on the spot.
static let extrapolationCapDouble1.5Ceiling on the interpolation parameter: 1.0 is the newest fix, so 1.5 is half an interval past it, and beyond that the value holds still. A late fix should not freeze the camera dead, but neither should a stalled feed send it gliding away, the further it runs on a guess, the bigger the snap back when the truth lands. Half an interval absorbs ordinary jitter without ever overshooting far enough to see. Same value and same semantics as the Android side's EXTRAPOLATION_CAP.
static let minFixIntervalTimeInterval0.10The measured inter-fix interval is clamped to this range before it paces anything, so one absurd gap (a suspended app, a debugger pause) cannot make the camera crawl or bolt. Ceiling mirrors the 1400 ms clamp MapMapNav's ChaseLayer puts on its per-fix ease duration; the floor sits at 100 ms (below MapMapNav's 140 ms) so the demo's 8x replay cadence of 125 ms interpolates instead of binding on the clamp, which left a residual fix-interval stutter. The Android side mirrors both bounds.
static let maxFixIntervalTimeInterval1.4
static let nominalFixIntervalTimeInterval1.0Assumed interval before two fixes have been seen (fixes are ~1 Hz), and the value the pacing window is seeded with. Seeding matters: with an empty window a single burst gap would be the median and collapse the pace to the floor.
static let intervalWindowInt3How many recent inter-fix gaps the pacing interval is the median of, the Android side's INTERVAL_WINDOW. Three is the smallest window with a median at all, and it is enough: one anomalous gap (a burst of two fixes 40 ms apart, a single late one) is outvoted by its two neighbours, while a genuine change of cadence, the demo's 8x replay, a provider switching rate, is adopted after two fixes rather than being damped away. Larger windows only add lag to that adoption.
static let onRouteToleranceMDouble25How far off the route a fix may project and still be treated as on it, in metres, the Android side's OFF_ROUTE_LATERAL_M. The fix a follow camera should be fed is already route-snapped (GuidanceDisplay.snappedFix), so on-route projections land within centimetres; this only has to be wide enough for a raw fix on the carriageway and tight enough that a genuine excursion (a wrong turn, a parallel service road) stops pretending to be on the route.
static let tangentWindowMDouble15Half-width, in metres, of the window the route tangent is measured over, the Android side's TANGENT_WINDOW_M. Taking the tangent from a single polyline segment makes a right-angle corner flip the bearing over a couple of metres, which on a course-up camera is a snap. Measuring it as the chord across ±15 m spreads that turn over 30 m of driving instead. Note this smoothing is spatial, not temporal: a route-derived bearing gets no exponential filter on top of it. The wobble that filter exists for, noisy per-fix course, is not in the route geometry, and a distance-based window makes the corner look the same at any speed, which is what lets the two platforms match.
var hasFixBoolTrue once at least one fix has been fed.
var latestBearingDegDouble?The low-passed bearing as of the newest fix, in degrees [0, 360). nil before the first fix. Exposed for tests and diagnostics; rendering should use state(at:), which interpolates towards it.
var fixIntervalTimeIntervalThe raw span between the two newest fixes, or nominalFixInterval before two have been seen. Diagnostics only: what actually paces the camera is pacingInterval, which is clamped and median-filtered.
var pacingIntervalTimeIntervalThe interval the camera is actually paced by: the median of the last intervalWindow clamped inter-fix gaps, seeded with nominalFixInterval. A median rather than the single last gap because one anomalous gap must not redefine the pace. Two fixes 40 ms apart followed by ordinary 1 Hz delivery would otherwise set the interval to the 100 ms floor, run the interpolation parameter to extrapolationCap within 190 ms, freeze the pose for the rest of the second, and then snap it backwards when the next fix rolled the segment over. Mirrors the Android side's pacingIntervalMs. Distinct from fixInterval, which is the raw span between the two newest fixes and is reported for diagnostics only.
var isFollowingRouteBoolTrue when a route is set and both of the two newest fixes projected onto it, i.e. state(at:) is following the road, not a chord across it.

Initialisers and methods

  • public init()
  • public mutating func setRoute(coordinates: [CLLocationCoordinate2D]): Give the interpolator the route the vehicle is driving, so that it interpolates along the road instead of straight between fixes. Why this matters: fixes arrive about a second apart, which at urban speed is 10–15 m. Interpolating in a straight line between two of them cuts every corner, through a bend the interpolated point leaves the route line, and the puck visibly drifts off the road and back on again. Interpolating in arc length along the route and emitting the point on the polyline cannot do that: every position it reports is a point of the route. The cumulative-distance table is built once, here. Rebuilding it per tick is the mistake that froze MapMapNav's JS thread (src/state/guidance/routeProgress.ts documents the same precompute); this type projects a fix onto the route once per fix (~1 Hz), and the per-frame query is a binary search and a lerp. Pass the route geometry in order. Fewer than two points clears it. Both stored fixes are re-snapped onto the new geometry here. A sample's alongM is an arc length measured against whatever polyline was current when the fix arrived, and state(at:) evaluates it against whatever polyline is current now, so carrying the old numbers across a reroute reads "2 km along route A" as "2 km along route B" and puts the camera wherever that happens to land, which on a reroute starting elsewhere is a jump of degrees of latitude (reproduced on the Android side). The re-snap honours onRouteToleranceM exactly as feed(coordinate:courseDeg:speedMps:timestamp:) does, so a pose the new route does not pass near loses its match and falls back to point-to-point rather than being dragged onto a line it was never on.
  • public mutating func feed(coordinate: CLLocationCoordinate2D, courseDeg: Double?, speedMps: Double?, timestamp: TimeInterval): Feed one guidance fix. - Parameters: - coordinate: the position to follow. Use the route-snapped fix (GuidanceDisplay.snappedFix), never the raw one: raw GPS drifts off the carriageway, and on a course-up camera that reads as the whole world shaking. - courseDeg: course over ground, degrees clockwise from true north. Values outside [0, 360) are wrapped. - speedMps: speed over ground. Below standstillSpeedMps the bearing is frozen (see the property). - timestamp: monotonic seconds on the host's clock, the fix's arrival time (see the type's "Clock" note). Fixes that are out of order, simultaneous with the newest one, or non-finite are ignored: replaying them would send the camera backwards.
  • public func state(at timestamp: TimeInterval) -> (coordinate: CLLocationCoordinate2D, bearingDeg: Double)?: The camera position and bearing to render at timestamp. nil before the first fix, the host should leave the camera where it framed the route. Behaviour, in the order the cases arise: - first fix: snaps to it (nothing to interpolate between); - healthy feed: linear interpolation between the two newest fixes, one interval behind live (see the type's "Presentation lag" note); - late fix: keeps going along the last segment, but only as far as extrapolationCap, half an interval past the newest fix; - stale feed: holds at that capped point. With a route set (setRoute(coordinates:)) and both fixes on it, the interpolation runs in arc length along the route and the position returned is a point on the route line, with the bearing taken from the route's own direction there. Without a route, or once a fix projects further than onRouteToleranceM off it, it falls back to interpolating the two fixes directly. The fallback interpolates linearly in latitude/longitude. Over one fix interval of driving (tens of metres) the difference from a great-circle path is far below a pixel, so the cheap form is the honest one. It does not handle a segment crossing the antimeridian; no MapMap route fixture does.
  • public static func wrap360(_ degrees: Double) -> Double: Normalise to [0, 360).
  • public static func shortestArcDelta(from: Double, to: Double) -> Double: Signed shortest-arc difference from -> to, in [-180, 180). Positive is clockwise. The half-open range matches shortestArcDeltaDeg on the Android side down to the boundary: an exact 180 degree reversal resolves anticlockwise on both platforms rather than one each way.

Struct · Sources/MapMapKit/Navigation/NavigationState.swift

swift
public struct NavigationState: Equatable, Sendable

One guidance emission: the fix that produced it plus the core's verdict.

GuidanceUpdate is the Rust core's state, navigating, arrived or offRoute, and the single source of truth. This wrapper only adds the triggering sample and display conveniences.

PropertyTypeDefaultDescription
let fixLocationSample
let updateGuidanceUpdate
var isArrivedBoolTrue once the core reports arrival at the destination.
var needsRerouteBoolTrue when the user has left the route entirely and the app should request a recalculation (build a new route + NavigationEngine).

Initialisers and methods

  • public init(fix: LocationSample, update: GuidanceUpdate)

ReplayLocationProvider

Struct · Sources/MapMapKit/Navigation/ReplayLocationProvider.swift

swift
public struct ReplayLocationProvider: LocationProvider

Replays a .drive.jsonl corpus (the sn-replay QA format) as a LocationProvider.

Fix timestamps in the corpus are relative to drive start; they are rebased onto epochStartMs so guidance sees monotonic wall-clock-like times.

PropertyTypeDefaultDescription
var locationsAsyncThrowingStream<LocationSample, Error>

Initialisers and methods

  • public init(corpus: DriveCorpus, timeScale: Double = 1.0, epochStartMs: Int64 = 0): - Parameters: - corpus: a parsed corpus (see DriveCorpus/parse(_:)). - timeScale: playback speed: 1.0 = real time, 2.0 = twice as fast, 0.0 = emit every fix immediately (unit tests). - epochStartMs: epoch milliseconds assigned to the first fix.

SignedChannelIndex

Struct · Sources/MapMapKit/Territory/ChannelSource.swift

swift
public struct SignedChannelIndex: Equatable, Sendable

The exact served bytes of a channel index and its detached signature.

PropertyTypeDefaultDescription
let jsonString
let signatureBase64String

SpeechSessionRefCount

Struct · Sources/MapMapKit/Navigation/VoiceGuidance.swift

swift
public struct SpeechSessionRefCount: Equatable, Sendable

Ref-count of in-flight utterances, deciding when the shared audio session may be deactivated (so ducked music comes back up), pure and unit-testable anywhere, like VoiceProsody. The platform wiring in VoiceGuidance mutates it under a lock: AVSpeechSynthesizer delegate callbacks arrive on an arbitrary queue.

PropertyTypeDefaultDescription
var outstandingInt0Utterances handed to the synthesiser that have not yet finished or been cancelled.

Initialisers and methods

  • public init()
  • public mutating func willSpeak(): Record one utterance handed to the synthesiser.
  • public mutating func didEnd() -> Bool: Record one utterance finishing or being cancelled. Returns true when that was the last one, nothing is speaking or queued, so the audio session should be deactivated. Spurious callbacks after a reset() never trigger another deactivation.
  • public mutating func reset() -> Bool: Clear everything (stop()). Returns true when there was anything outstanding, i.e. the session should be deactivated.

VoiceProsody

Struct · Sources/MapMapKit/Navigation/VoiceGuidance.swift

swift
public struct VoiceProsody: Equatable, Sendable

Prosody and earcon policy per InstructionSeverity, pure and unit-testable anywhere (the platform wiring lives in VoiceGuidance).

The core derives severity (see InstructionSeverity in crates/sn-nav-core): .info for routine manoeuvres, .warning when approaching a restriction (toll, ferry, and off-route), .critical for prohibitions (ADR tunnel block, gate).

PropertyTypeDefaultDescription
let rateFloat`AVSpeechUtterance` rate (0–1 scale; the platform default is `AVSpeechUtteranceDefaultSpeechRate`)AVSpeechUtterance rate (0–1 scale; the platform default is AVSpeechUtteranceDefaultSpeechRate).
let pitchMultiplierFloatUtterance pitch multiplier (1.0 = neutral).
let interruptBoolWhether pending speech is stopped before this prompt.

Initialisers and methods

  • public static func prosody(for severity: InstructionSeverity, baseRate: Float = AVSpeechUtteranceDefaultSpeechRate) -> VoiceProsody: Prosody for severity at baseRate (defaults to the platform's default speech rate). Critical prompts speak slightly faster, clamped to the platform maximum.
  • public static func earconName(for severity: InstructionSeverity) -> String?: The earcon resource name for severity, or nil when the severity plays none by default (info stays silent so a chime does not precede every routine manoeuvre). Assets are generated by scripts/generate-earcons.py.
  • public static func earconURL(for severity: InstructionSeverity) -> URL?: URL of the earcon WAV inside MapMapKit's resource bundle, or nil for severities that play none.

Enums (MapMapKit)

AdrCompliance, ChannelSourceError, ChannelSync, GuidanceDisplay, MapMap, MapMapKitError, OfflineRouting, ProbeUploadOutcome, TerritoryKeys, ValhallaConfigWriter

AdrCompliance

Enum · Sources/MapMapKit/Adr/AdrCompliance.swift

swift
public enum AdrCompliance

On-device ADR 8.6.4 dangerous-goods enforcement.

Two enforcement points, both running the same Rust domain model (sn-adr, conservative ADR 8.6.4 reading):

  1. Pre-route, pass the AdrProfile to OfflineRouting/route(router:waypoints:costing:adr:); the core merges the restrictions into Valhalla truck costing, so forbidden tunnels and undersized roads are excluded before a route exists.
  2. En-route, call checkTunnel(profile:category:) against a tunnel's category (e.g. from map data ahead of the vehicle) to gate entry while driving, and forbiddenCategories(profile:) to badge the whole profile in the UI.

Initialisers and methods

  • public static func checkTunnel(profile: AdrProfile, category: AdrTunnelCategory) -> AdrDecision: May the vehicle described by profile pass through a tunnel of category? Blocked decisions carry a human-readable reason citing ADR 8.6.4.
  • public static func forbiddenCategories(profile: AdrProfile) -> [AdrTunnelCategory]: All tunnel categories the vehicle is forbidden from, ascending. Empty when unrestricted.
  • public static func isTunnelRestricted(profile: AdrProfile) -> Bool: True when the profile is barred from at least one tunnel category.
  • public static func validateProfile(_ profile: AdrProfile) -> [String]: Validate a profile's physical plausibility before it goes anywhere near routing. Returns a list of human-readable problems; empty means valid. Pure Swift, safe to call from previews and tests without the native library.

ChannelSourceError

Enum · Sources/MapMapKit/Territory/ChannelSource.swift

swift
public enum ChannelSourceError: Error, Equatable, CustomStringConvertible

Why a ChannelSource could not be built.

PropertyTypeDefaultDescription
var descriptionString
CaseDescription
notACustomRegion(String)
notAnIndexURL(String)
noRegionKeyThe store was built without a region key, so it refuses every custom region.

ChannelSync

Enum · Sources/MapMapKit/Territory/TerritoryStore.swift

swift
public enum ChannelSync: Sendable

What TerritoryStore/sync(territoryId:indexJson:indexSigBase64:fetcher:omit:cancel:) did.

CaseDescription
installed(ChannelInstallResult)The territory was not installed; the channel's latest version now is.
updated(UpdateResult)An older version was installed; it was updated in place.
upToDate(TerritoryInfo)Already on the channel's latest version; nothing was downloaded.
cancelledThe CancelToken was tripped; nothing changed on disk.

GuidanceDisplay

Enum · Sources/MapMapKit/Navigation/NavigationState.swift

swift
public enum GuidanceDisplay

Pure display mappers for GuidanceUpdate. Kept free of native calls so they are unit-testable anywhere.

Initialisers and methods

  • public static func instruction(_ update: GuidanceUpdate) -> String?: The instruction to show for the current update, if any.
  • public static func visualBanner(_ update: GuidanceUpdate) -> VisualBanner?: The visual banner for the upcoming manoeuvre, when one is active at the current distance (primary/secondary/sub lines with lane diagrams; render primary.text with the arrow named by primary.maneuverType/maneuverModifier).
  • public static func spokenPrompt(_ update: GuidanceUpdate) -> SpokenPrompt?: The spoken prompt currently due. Hand ssml ?? text to AVSpeechSynthesizer, and de-duplicate by utteranceId, the same prompt is reported on every update until it is superseded.
  • public static func severity(_ update: GuidanceUpdate) -> InstructionSeverity: How urgently the update should be surfaced (see the core's InstructionSeverity for the derivation). Off-route is a .warning, the driver has left the route and a recalculation is due; arrival is routine.
  • public static func snappedFix(_ update: GuidanceUpdate) -> SnappedFix?: The route-snapped position and course for the current update, if any. Drive follow-cameras from this, e.g. feed it into a MapLibre course-tracking camera (MapViewCamera.automotiveNavigation() style: course-up, zoom 16, pitch 45), never the raw fix, which jitters and drifts off the carriageway.
  • public static func speedLimit(_ update: GuidanceUpdate) -> SpeedLimit?: The posted speed limit for the current edge, when the route carries a maxspeed annotation at the current position. Render a speed-limit badge from .known(kmh:), and compare the fix's speed against it for an over-limit warning. nil with stock map data (no annotation); .unlimited/.unknown distinguish an explicit no-limit from an explicitly-unvalued annotation.
  • public static func formatDistance(_ metres: Double) -> String: Format a distance in metres for guidance display: metres under 1 km (10 m steps under 100 m, 50 m steps above), kilometres with one decimal from 1 km.
  • public static func summarise(_ update: GuidanceUpdate) -> String: One-line status suitable for a debug HUD or live activity.

MapMap

Enum · Sources/MapMapKit/MapMapKit.swift

swift
public enum MapMap

Entry point for the MapMap iOS SDK.

The SDK is a thin, idiomatic Swift layer over the Rust navigation core (sn-nav-core, linked as a static library inside MapMapFFI.xcframework). The raw UniFFI bindings, the mapmap component and the ferrostar component, which is compiled into the same library, live in Generated/; everything else in this module is the supported surface:

  • TerritoryStore, signed offline territory packages (install / verify / activate / update planning), actor-isolated.
  • OfflineRouting, on-device Valhalla routing with ADR dangerous-goods enforcement merged into every request.
  • AdrCompliance, pre-route and en-route ADR 8.6.4 tunnel checks.
  • NavigationEngine, turn-by-turn guidance over a computed route, fed by any LocationProvider (CoreLocationProvider live, ReplayLocationProvider for QA corpora).

Initialisers and methods

  • public static func ensureLoaded(): Eagerly verify that the bindings match the linked native core. Calling this is optional, the first native call performs the same UniFFI contract check lazily, but doing it at app start surfaces packaging problems (mismatched binding checksums, wrong framework slice) as an immediate, attributable crash instead of a mid-drive one.
  • public static func defaultGuidanceConfig() -> GuidanceConfig: A GuidanceConfig with the core's documented defaults.
  • public static func defaultAdrProfile() -> AdrProfile: An AdrProfile with the core's documented defaults: EU maximum authorised dimensions (Council Directive 96/53/EC), no dangerous goods.

MapMapKitError

Enum · Sources/MapMapKit/MapMapKit.swift

swift
public enum MapMapKitError: Error, Equatable, LocalizedError

Errors raised by the Swift layer itself, before a call ever crosses into the Rust core (which throws NavCoreError).

PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
incompatibleCosting(costing: CostingModel)An ADR profile was supplied with a costing model other than CostingModel/truck.
invalidArgument(String)A caller-supplied argument failed Swift-side validation.

OfflineRouting

Enum · Sources/MapMapKit/Routing/OfflineRouting.swift

swift
public enum OfflineRouting

On-device route computation.

The Rust core builds the Valhalla request (merging ADR dangerous-goods and dimensional costing options, rejecting conflicts), the injected OfflineRouter executes it against local tiles, and the core parses the response into a RouteResult whose valhallaResponseJson feeds NavigationEngine.

Initialisers and methods

  • public static func requireCompatibleCosting(costing: CostingModel, adr: AdrProfile?) throws: ADR profiles ride on Valhalla truck costing options; requesting any other costing model with an ADR profile is a contract violation the Rust core rejects. Checked here too so the failure is a fast, clearly-attributed MapMapKitError/incompatibleCosting(costing:) rather than a routing error after the FFI hop.
  • public static func route(router: LocalRouter, waypoints: [RoutePoint], costing: CostingModel = .auto, adr: AdrProfile? = nil) async throws -> RouteResult: Compute a route on-device. Routing is CPU-bound native work; it runs on a detached utility task, never on the caller's executor. - Parameters: - router: the on-device engine, usually a ValhallaMobileRouter. - waypoints: at least two RoutePoints, in visit order. - costing: the Valhalla costing model; must be CostingModel/truck when adr is supplied. - adr: optional dangerous-goods/dimensional profile, when set, the request is built with the restrictions merged in, so illegal roads and tunnels are excluded before the route exists. - Throws: NavCoreError/Routing(message:) when the engine returns a Valhalla error body (e.g. no route, no tiles for the area).
  • public static func buildRequest(waypoints: [RoutePoint], costing: CostingModel = .auto, adr: AdrProfile? = nil) throws -> String: Build the raw Valhalla request JSON without executing it, for callers that drive the engine themselves or log requests for audit.
  • public static func parseResponse(_ responseJson: String) throws -> RouteResult: Parse a raw engine response into a RouteResult.

ProbeUploadOutcome

Enum · Sources/MapMapKit/Navigation/ProbeContribution.swift

swift
public enum ProbeUploadOutcome: Sendable, Equatable

The outcome of one upload attempt, surfaced through URLSessionProbeUploader's result callback for observability and tests.

CaseDescription
accepted202, accepted and stored.
refused403, the key is not opted in; dropped, not retried.
notEnabled501, server collection is not enabled (SN_PROBE_DIR unset); dropped.
rejected400/other 4xx, malformed or unacceptable; dropped, not retried.
gaveUpTransport error or 5xx after exhausting retries; given up on.

TerritoryKeys

Enum · Sources/MapMapKit/Territory/TerritoryKeys.swift

swift
public enum TerritoryKeys

The public halves of the keys that sign MapMap's hosted territory packages, for pinning in an app. Both are ed25519 public keys as 64 hex characters, the form TerritoryStore takes.

Pin them at build time; never read either from the network. An app that runs its own factory or region signer passes its own keys instead.

PropertyTypeDefaultDescription
static let hostedFactoryKeyHexThe factory key: verifies every country package on the hosted channel (https://api.mapmap.ai/territories). Also published at mapmap.ai/docs/territories.
static let hostedRegionKeyHexThe region key: verifies custom regions (region- ids) cut by the hosted gateway (POST /v1/jobs/territory). The core accepts it for region- ids only, and never the factory key for them, so a leaked region key cannot forge a country package. Pass it as TerritoryStore(rootDir:verifyingKeyHex:regionKeyHex:).

ValhallaConfigWriter

Enum · Sources/MapMapKit/Routing/OfflineRouting.swift

swift
public enum ValhallaConfigWriter

Writes the valhalla.json the on-device Valhalla engine needs.

The document is Valhalla's own complete default config (valhalla_build_config, MIT, https://github.com/valhalla/valhalla/blob/master/scripts/valhalla_build_config), bundled as Resources/valhalla-defaults.json, with the tile source and a mobile-sized cache set on top. The engine reads many keys (every service_limits section, loki, thor, meili) with no compiled-in fallback: a config carrying only mjolnir makes every route fail with "No such node (service_limits.isochrone.max_contours)", which is what this writer produced before (found on an Android device; the Android writer bundles the same file).

PropertyTypeDefaultDescription
static let defaultMaxCacheBytesInt64268_435_456Mobile default for mjolnir.max_cache_size (bytes): 256 MiB.

Initialisers and methods

  • public static func configJSON(tileDir: URL, maxCacheBytes: Int64 = defaultMaxCacheBytes) throws -> String: Render the config document for a routing-tile directory (the territory's MapLayerKind/valhallaTiles layer).

Protocols (MapMapKit)

LocationProvider, OfflineRouter, ProbeUploader

LocationProvider

Protocol · Sources/MapMapKit/Navigation/LocationProvider.swift

swift
public protocol LocationProvider: Sendable

A source of location fixes for NavigationEngine.

Implementations: CoreLocationProvider (Core Location) for live navigation, ReplayLocationProvider (a .drive.jsonl corpus) for QA and demos. Any stream of samples in ascending timestamp order qualifies.

The stream is cold: every access to locations starts a fresh sequence, and it is consumed once per navigation session.

PropertyTypeDefaultDescription
var locationsAsyncThrowingStream<LocationSample, Error>A fresh stream of fixes. Finishes when the source is exhausted (replay) or throws on unrecoverable platform errors (live).

OfflineRouter

Protocol · Sources/MapMapKit/Routing/OfflineRouting.swift

swift
public protocol OfflineRouter: LocalRouter

An on-device routing engine.

This is the Rust core's LocalRouter callback interface with a Swift name: implementations execute a Valhalla turn-by-turn request JSON synchronously and return the raw response JSON (either a route response or a Valhalla error body, the core parses and classifies both).

The production implementation is ValhallaMobileRouter in the MapMapValhalla product (iOS only, it wraps the valhalla-mobile engine); tests inject fakes that return canned responses.

ProbeUploader

Protocol · Sources/MapMapKit/Navigation/ProbeContribution.swift

swift
public protocol ProbeUploader: Sendable

Where a completed probe batch goes. Called off the guidance stream, so enqueue(_:) must not block and must never throw.

Initialisers and methods

  • func enqueue(_ body: String): Hand one probe body, the string from ProbeCollector.finishJson, off to be POSTed to /v1/probe. Fire-and-forget.

Functions (MapMapKit)

contributingProbe

contributingProbe

Function · Sources/MapMapKit/Navigation/ProbeContribution.swift

swift
public func contributingProbe(_ upstream: AsyncThrowingStream<NavigationState, Error>, config: ProbeConfig, uploader: ProbeUploader, routeRef: String? = nil, territory: String? = nil, vehicleClass: String? = nil, now: @escaping @Sendable () -> Int64 = { Int64(Date().timeIntervalSince1970 * 1000) }) -> AsyncThrowingStream<NavigationState, Error>

Accumulate an aggregate probe batch from a guidance stream and upload it when the trip ends. A transparent pass-through when config.enabled is false (the shipped default): no collector is constructed and nothing is uploaded, so leaving collection off costs nothing.

Wrap it around NavigationEngine/navigate(provider:)'s stream: swift let stream = contributingProbe( await engine.navigate(provider: provider), config: ProbeConfig(enabled: consentGranted), uploader: URLSessionProbeUploader(baseURL: "https://api.mapmap.ai", apiKey: key), routeRef: servedRouteToken, territory: "uk", vehicleClass: "truck_40t" ) for try await state in stream { render(state) }

Consent is the caller's responsibility: only pass enabled: true for a key whose operator has set probe_opt_in and, for a consumer app, with the user's opt-in consent. See docs/PROBE-SDK-INTEGRATION.md.

Only aggregates leave the device: the collector cannot emit a trajectory, and the first/last stretch of every trip is discarded on-device.

  • Parameters:
    • routeRef: opaque served-route token so the server can resolve segment indices.
    • vehicleClass: a costing class only, never a registration, VIN or driver id.
    • now: injectable clock (Unix millis) for deterministic tests.

MapMap core bindings (generated)

Classes (MapMap core bindings (generated))

CancelToken, GuidanceSession, LayerFetcherImpl, LocalRouterImpl, ProbeCollector, TerritoryManager, TerritorySearch

CancelToken

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class CancelToken: CancelTokenProtocol, @unchecked Sendable

A cancellation handle for an in-flight territory install or update.

The install calls on TerritoryManager block the calling thread for as long as a multi-gigabyte package takes to download, unpack and verify. Create a token, pass it to one of the _cancellable variants running on a background thread, and call [CancelToken::cancel] from the UI thread when the user taps Cancel. The install polls it at safe points and returns [InstallOutcome::Cancelled] / [UpdateOutcome::Cancelled] with its staging directory removed: no partial package is left on disk, the previously installed version is untouched, and layers that had already been verified stay in the resumable cache for the next attempt. Cancelling after the call has returned changes nothing.

The token cannot interrupt a LayerFetcher blocked in a transfer: give the fetcher the same token and have it poll [CancelToken::is_cancelled] between chunks (or abort its request when the app cancels). Whatever the fetcher then returns, the install reports Cancelled, not a transport error.

Initialisers and methods

  • public convenience init(): A fresh, uncancelled token.
  • open func cancel(): Request cancellation. Idempotent and safe from any thread.
  • open func isCancelled() -> Bool: Whether [Self::cancel] has been called.
GuidanceSession

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class GuidanceSession: GuidanceSessionProtocol, @unchecked Sendable

A turn-by-turn guidance session (see [crate::guidance]).

Thread-safe: the mutable Ferrostar navigation state is guarded by a mutex, matching UniFFI's shared-object concurrency model.

Initialisers and methods

  • public convenience init(routeResponseJson: String, config: GuidanceConfig) throws: Create a session from a Valhalla route response JSON (as returned by route_offline in valhalla_response_json).
  • open func advanceToNextStep() throws -> GuidanceUpdate: Manually advance to the next step (e.g. in a tunnel with no GNSS).
  • open func totalSteps() -> UInt32: Number of steps in the route, including the arrival step.
  • open func updateLocation(lat: Double, lon: Double, timestampMs: Int64, speedMps: Double?, courseDeg: Double?, horizontalAccuracyM: Double?) throws -> GuidanceUpdate: Feed a location fix; returns the updated guidance state. horizontal_accuracy_m defaults to 0.0 (trusted exactly) when absent; pass the platform's reported accuracy when available so step advance and deviation gating behave correctly.
LayerFetcherImpl

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class LayerFetcherImpl: LayerFetcher, @unchecked Sendable

The platform's download transport for over-the-air territory updates, exported as a UniFFI callback interface like [crate::routing::LocalRouter]: the core decides what to fetch and cryptographically verifies everything; Kotlin/Swift decide how bytes move (OkHttp, URLSession, an air-gapped mirror, …).

Initialisers and methods

  • open func fetch(relPath: String, expectedBlake3: String, destPath: String) throws: Download the channel-relative rel_path (e.g. territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local file dest_path. expected_blake3 is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouterImpl

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class LocalRouterImpl: LocalRouter, @unchecked Sendable

The injection point for the platform's on-device Valhalla binding.

valhalla-mobile (https://github.com/Rallista/valhalla-mobile) exposes a route(request_json) -> response_json actor on both Android and iOS; Kotlin/Swift implement this interface with that actor and pass it to [crate::ffi::route_offline]. Exported as a UniFFI callback interface (with_foreign) so the implementation lives in foreign code.

Initialisers and methods

  • open func route(requestJson: String) -> String: Execute a Valhalla turn-by-turn request and return the raw response JSON (either a route response or a Valhalla error body).
ProbeCollector

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class ProbeCollector: ProbeCollectorProtocol, @unchecked Sendable

On-device probe collector. Feed it every guidance update with the fix's position, speed and timestamp; call finish at arrival or trip abandonment to get the ProbeBatch to upload.

Interior mutability (a Mutex) lets the FFI methods take &self, matching the [crate::guidance::GuidanceSession] object shape.

Initialisers and methods

  • public convenience init(config: ProbeConfig): Create a collector with the given configuration.
  • open func finish(arrived: Bool, timestampMs: Int64) -> ProbeBatch: Close the trip and return the batch to upload. arrived distinguishes a completed trip from an abandoned one (both apply end suppression).
  • open func finishJson(arrived: Bool, timestampMs: Int64) -> String?: Close the trip and return the exact JSON body to POST /v1/probe, or None when the batch carries nothing worth uploading. This is the single canonical serialiser for the probe wire format, platform code should upload this verbatim rather than re-encoding the record, so the wire form can never drift from what the gateway ingests.
  • open func observe(update: GuidanceUpdate, fixLat: Double, fixLon: Double, speedMps: Double?, timestampMs: Int64): Feed one guidance update and its fix. speed_mps is the device's reported ground speed when available (preferred); pass None to let the collector estimate it from successive positions.
  • open func setRouteRef(routeRef: String): Set the opaque served-route token so the server can resolve segments.
  • open func setTerritory(territory: String): Set the territory id stamped into the batch.
  • open func setVehicleClass(vehicleClass: String): Set the vehicle costing class stamped into the batch (a class only, never a vehicle or driver identifier).
TerritoryManager

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class TerritoryManager: TerritoryManagerProtocol, @unchecked Sendable

Manages signed offline territory packages (see [crate::territory]).

Initialisers and methods

  • public convenience init(rootDir: String, verifyingKeyHex: String) throws: Open a manager rooted at root_dir, trusting packages signed by the ed25519 public key given as 64 hex characters (the factory signing key's public half, [sn_package::VerifyingKey::to_hex]).
  • public static func withRegionKey(rootDir: String, verifyingKeyHex: String, regionKeyHex: String) throws -> TerritoryManager: [Self::new], also trusting custom regions (region-… ids, cut by POST /v1/jobs/territory) signed by region_key_hex, the public half of the gateway's region signing key. The keys are partitioned by id: the region key verifies region- ids only and the factory key everything else. Pin both in the app; never read either from the network.
  • open func active() throws -> String?: The active territory id, if one is set and still installed.
  • open func applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher) throws -> UpdateResult: Apply a differential update: stage, fetch only the changed layers through fetcher, verify everything and swap atomically. Any failure leaves the installed territory untouched; the active flag is preserved. Blocks until done and cannot be interrupted; see [Self::apply_update_cancellable].
  • open func applyUpdateCancellable(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken) throws -> UpdateOutcome: [Self::apply_update] with a CancelToken. Polled before every layer download, between archive entries while unpacking, before each hash pass and before promotion. A tripped token yields [UpdateOutcome::Cancelled]: the installed version is untouched, staging is removed, and layers that had already been fetched and verified stay in the resumable cache, so calling again with the same manifest re-fetches only what is missing. Give fetcher the same token so it can stop an in-flight transfer (the token cannot interrupt foreign code on its own); whatever the fetcher then returns, a tripped token reports Cancelled rather than a transport error.
  • open func cachedLayerBytes() throws -> UInt64: Bytes parked in the resumable layer cache: downloads a failed install already paid for, which a retry will not pay for again. Surface this next to a "resume" affordance and in storage settings.
  • open func checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher) throws -> AvailableUpdate?: Check the signed channel index for an update to an installed territory. index_json must be the exact bytes served as index.json and index_sig_base64 the content of index.json.sig; the remote manifest is fetched and verified through fetcher. Returns None when the device is already on the channel's latest version (or the channel does not list the territory).
  • open func clearLayerCache() throws: Discard every parked layer. The bytes are lost and a later install re-downloads (and on a metered channel re-pays for) them, so offer this only as a deliberate "free up space" action.
  • open func installDir(packageDir: String) throws -> TerritoryInfo: Install an unpacked package directory. Blocks until done and cannot be interrupted; see [Self::install_dir_cancellable].
  • open func installDirCancellable(packageDir: String, cancel: CancelToken) throws -> InstallOutcome: [Self::install_dir] with a CancelToken. Polled between copied files, before verification and before promotion.
  • open func installDirPartial(packageDir: String, omit: [MapLayerKind], cancel: CancelToken) throws -> InstallOutcome: Install an unpacked package directory, holding only the layers this app can use: omit names the kinds to leave out (e.g. Pmtiles and Extra("style") for an app with no map view). The install records what it left out, and every later verification requires those layers to be absent rather than exempting them from hashing, so the record cannot be forged into admitting tampered bytes. Asking for an omitted layer answers [NavCoreError::LayerNotInstalled], which is not an error state: it is "you chose not to download this". The selection is sticky: updates carry it forward, so an app that skipped the render layers never downloads them on an update either.
  • open func installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, omit: [MapLayerKind], fetcher: LayerFetcher, cancel: CancelToken) throws -> ChannelInstallOutcome: Install a territory from the channel, downloading only the layers this app can use. The first-install counterpart of [Self::apply_update], and the only path on which omitting layers saves bandwidth: a layer in omit is never requested, so it is never metered and never stored. index_json / index_sig_base64 are the exact served bytes of index.json and index.json.sig; the channel's latest version of the territory is installed. Nothing is trusted but the pinned key: the index signature, the manifest signature and every blob's BLAKE3 are checked, and the assembled directory goes through the same full verification pass as any other install before it is promoted. Interrupted installs resume: verified layers stay parked in the layer cache. Calling it again for a territory that is already installed is how a selection is widened later. Layers already on the device at the same content hash are linked, not re-downloaded, so adding the map to a router-only install costs the map alone.
  • open func installSnpkg(archivePath: String) throws -> TerritoryInfo: Install a packed .snpkg archive (verify-then-promote; rejected packages leave no trace). Blocks until done and cannot be interrupted; see [Self::install_snpkg_cancellable].
  • open func installSnpkgCancellable(archivePath: String, cancel: CancelToken) throws -> InstallOutcome: [Self::install_snpkg] with a CancelToken. Polled between archive entries, before verification and before promotion; a tripped token yields [InstallOutcome::Cancelled] with staging removed and nothing installed.
  • open func installSnpkgPartial(archivePath: String, omit: [MapLayerKind], cancel: CancelToken) throws -> InstallOutcome: [Self::install_dir_partial] from a packed .snpkg archive. The archive carries every layer, so this saves storage, not bandwidth: the omitted layers are unpacked and then dropped before verification. For the bandwidth saving use [Self::install_from_channel], which never fetches a blob it does not want.
  • open func layerPath(territoryId: String, kind: MapLayerKind) throws -> String: Absolute path of a layer inside an installed territory (e.g. the Valhalla tile tree for valhalla-mobile, the PMTiles file for MapLibre).
  • open func list() throws -> [TerritoryInfo]: List installed territories in territory-id order.
  • open func openSearch(territoryId: String) throws -> TerritorySearch: Open the installed territory's bundled geocode index for on-device search. The returned TerritorySearch holds the index open (mmap-backed), create it once per territory and reuse it across queries.
  • open func planUpdate(newManifestJson: String) throws -> UpdatePlan: Plan a differential update from the installed manifest to new_manifest_json (a signed manifest's JSON body, as served by the update channel).
  • open func remove(territoryId: String) throws: Remove an installed territory (clears the active marker if needed).
  • open func setActive(territoryId: String) throws: Mark a territory as active (persisted atomically).
  • open func territoryStyle(territoryId: String, theme: StyleTheme) throws -> String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK's buildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via a pmtiles://<absolute path> URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly over the package's PMTiles layer. The glyphs endpoint stays hosted (MapLibre caches fetched glyph ranges; no offline glyph bundle ships in packages today).
  • open func verifyTerritory(territoryId: String) throws -> TerritoryInfo: Re-verify an installed territory from disk: the manifest signature, the BLAKE3 of every layer this install holds, and the absence of every layer it recorded as omitted. The ordinary calls do not re-hash gigabytes; this is the on-demand integrity check for after a restore or a crash. A failure arrives as [NavCoreError::Verification] and means the install must be repaired or reinstalled, not retried.
TerritorySearch

Class · Sources/MapMapKit/Generated/mapmap.swift

swift
open class TerritorySearch: TerritorySearchProtocol, @unchecked Sendable

On-device search over an installed territory's bundled geocode index (see [TerritoryManager::open_search]). Fully offline; queries are synchronous and mmap-backed, call from a background thread/dispatcher like any other disk-bound SDK call.

Initialisers and methods

  • open func reverse(lat: Double, lon: Double, limit: UInt32) throws -> [Place]: Reverse geocode: the nearest indexed places to a coordinate, nearest first.
  • open func search(query: String, near: RoutePoint?, limit: UInt32) throws -> [Place]: Free-text search (addresses, streets, places, POIs, UK postcodes; prefix-tokenised, so it works for search-as-you-type). near biases ranking towards the given point and fills each result's distance_m; limit caps the number of hits.

Structs (MapMap core bindings (generated))

AdrProfile, AvailableUpdate, BannerLine, ChangedLayer, ChannelInstallResult, FasterRouteCandidate, FasterRouteConfig, FasterRouteRecommendation, GuidanceConfig, LaneGuidance, OdRecord, Place, ProbeBatch, ProbeConfig, RerouteAnchor, RerouteConfig, RerouteDecision, RerouteWaypoint, RouteManeuver, RoutePoint, RouteResult, RouteSummary, SegmentAggregate, SnappedFix, SpokenPrompt, TerritoryInfo, UpdatePlan, UpdateResult, VisualBanner

AdrProfile

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct AdrProfile: Equatable, Hashable

Vehicle profile for ADR and dimensional enforcement, mirroring [sn_adr::AdrVehicleProfile]. Defaults are the EU maximum authorised dimensions (Council Directive 96/53/EC) with no dangerous goods.

PropertyTypeDefaultDescription
var heightMDoubleVehicle height in metres.
var widthMDoubleVehicle width in metres.
var lengthMDoubleVehicle length in metres.
var grossWeightTDoubleGross combination weight in metric tonnes.
var axleLoadTDouble?Heaviest single-axle load in tonnes, if known.
var axleCountUInt32?Number of axles, if known.
var hazmatBoolWhether the vehicle carries dangerous goods at all.
var tunnelCodeAdrTunnelCode?Declared ADR tunnel restriction code. None with hazmat = true means "dangerous goods of unknown code" and is treated as code B (most restrictive non-quantity code).

Initialisers and methods

  • public init(heightM: Double = Double(4.0), widthM: Double = Double(2.55), lengthM: Double = Double(16.5), grossWeightT: Double = Double(40.0), axleLoadT: Double? = nil, axleCount: UInt32? = nil, hazmat: Bool = false, tunnelCode: AdrTunnelCode? = nil)
AvailableUpdate

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct AvailableUpdate: Equatable, Hashable

An update the channel offers for an installed territory.

PropertyTypeDefaultDescription
var versionStringThe channel's latest version for the territory.
var changedLayers[ChangedLayer]Layers that must be downloaded.
var installedBytesUInt64Uncompressed total of the changed layers, on-device disk, not metered wire bytes. Same warning as [UpdatePlan::installed_bytes].
var manifestJsonStringThe remote manifest's exact JSON text; pass verbatim to [TerritoryManager::apply_update].
var manifestSigStringThe remote manifest's detached base64 ed25519 signature.

Initialisers and methods

  • public init(version: String, changedLayers: [ChangedLayer], installedBytes: UInt64, manifestJson: String, manifestSig: String)
BannerLine

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct BannerLine: Equatable, Hashable

One line of a visual banner (primary/secondary/sub).

PropertyTypeDefaultDescription
var textStringText to display.
var maneuverTypeString?Standardised maneuver type for the arrow glyph (e.g. turn).
var maneuverModifierString?Standardised maneuver modifier (e.g. right).
var roundaboutExitDegreesUInt16?Degrees travelled around a roundabout before exiting, when known.
var exitNumbers[String]Exit numbers (e.g. 8B), when signposted.
var lanes[LaneGuidance]Lane diagram entries (usually only on sub banners).

Initialisers and methods

  • public init(text: String, maneuverType: String?, maneuverModifier: String?, roundaboutExitDegrees: UInt16?, exitNumbers: [String], lanes: [LaneGuidance])
ChangedLayer

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct ChangedLayer: Equatable, Hashable

One layer that a territory update must download.

PropertyTypeDefaultDescription
var kindStringThe layer kind's kebab-case string.
var pathStringPath of the layer relative to the package root.
var bytesUInt64Layer size in bytes.

Initialisers and methods

  • public init(kind: String, path: String, bytes: UInt64)
ChannelInstallResult

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct ChannelInstallResult: Equatable, Hashable

What [TerritoryManager::install_from_channel] did.

PropertyTypeDefaultDescription
var territoryTerritoryInfoThe installed territory.
var layersFetchedUInt32How many layer blobs were downloaded on this attempt.
var layersReusedUInt32How many layers cost nothing: already on the device at the same content hash, or parked by an attempt that failed before it could promote.
var bytesDownloadedUInt64Bytes downloaded on this attempt. Compressed blob bytes on the wire, so directly comparable with a metering allowance, unlike installedBytes, which is uncompressed disk.

Initialisers and methods

  • public init(territory: TerritoryInfo, layersFetched: UInt32, layersReused: UInt32, bytesDownloaded: UInt64)
FasterRouteCandidate

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct FasterRouteCandidate: Equatable, Hashable

One candidate route for the remaining journey, summarised from the router's response (a primary route or an alternate).

PropertyTypeDefaultDescription
var idString?Opaque identifier for the candidate (e.g. the response id or an alternate index), echoed back so the platform can find the route to switch to. Not interpreted by the evaluator.
var durationSDoubleThe candidate's estimated duration in seconds for the remaining journey, from the same response baseline as the current-route remaining ETA (recompute both from one response to avoid drift).

Initialisers and methods

  • public init(id: String?, durationS: Double)
FasterRouteConfig

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct FasterRouteConfig: Equatable, Hashable

Faster-route evaluator configuration, flattened for FFI like [crate::reroute::RerouteConfig].

PropertyTypeDefaultDescription
var checkIntervalSDoubleSeconds between checks. A check becomes due once this much time has elapsed since the last evaluation (or since the first observation).
var minSavingSUInt32Minimum absolute saving in seconds. Candidates saving less are never recommended.
var minSavingFracDoubleMinimum saving as a fraction of the current remaining time (0..1). Both this and min_saving_s must pass.
var dismissSuppressSDoubleSeconds a dismissal suppresses further recommendations. Within the window only a saving at least double the dismissed one re-prompts.
var maneuverBlackoutSDoubleSeconds-to-next-manoeuvre under which a due check is deferred; the check fires on the first observation clear of the blackout.
var enabledBoolWhether the evaluator is active at all. When false, checks are never due and evaluations never recommend.

Initialisers and methods

  • public init(checkIntervalS: Double = Double(120.0), minSavingS: UInt32 = UInt32(180), minSavingFrac: Double = Double(0.08), dismissSuppressS: Double = Double(600.0), maneuverBlackoutS: Double = Double(60.0), enabled: Bool = true)
FasterRouteRecommendation

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct FasterRouteRecommendation: Equatable, Hashable

A recommendation to switch to a faster candidate route.

PropertyTypeDefaultDescription
var savesSUInt32Estimated saving in seconds versus staying on the current route.
var candidateIdxUInt32Index into the candidate slice passed to [FasterRouteEvaluator::evaluate] of the winning candidate.

Initialisers and methods

  • public init(savesS: UInt32, candidateIdx: UInt32)
GuidanceConfig

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct GuidanceConfig: Equatable, Hashable

Guidance behaviour configuration, flattened for FFI.

Maps onto Ferrostar's NavigationControllerConfig: a distance-to-end-of-step advance condition, a static-threshold route deviation tracker and course snapping.

PropertyTypeDefaultDescription
var stepAdvanceDistanceMUInt16Advance to the next step when the user is within this many metres of the end of the current step.
var minimumHorizontalAccuracyMUInt16Location fixes with worse horizontal accuracy than this (metres) can neither advance a step nor flag a deviation.
var routeDeviationThresholdMDoubleThe user is off route when further than this many metres from the route line.
var snapCourseToRouteBoolSnap the reported course to the route line (true, recommended for vehicular navigation) or report the raw course (false).
var waypointAdvanceRangeMDoubleA waypoint is considered visited within this many metres.

Initialisers and methods

  • public init(stepAdvanceDistanceM: UInt16 = UInt16(20), minimumHorizontalAccuracyM: UInt16 = UInt16(25), routeDeviationThresholdM: Double = Double(25.0), snapCourseToRoute: Bool = true, waypointAdvanceRangeM: Double = Double(100.0))
LaneGuidance

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct LaneGuidance: Equatable, Hashable

One lane at the upcoming maneuver, for lane-diagram UIs.

PropertyTypeDefaultDescription
var directions[String]Turn directions this lane allows (OSRM indication strings, e.g. left, straight, slight right).
var activeBoolWhether guidance recommends this lane for the maneuver.
var activeDirectionString?Which of directions to highlight when the lane serves several.

Initialisers and methods

  • public init(directions: [String], active: Bool, activeDirection: String?)
OdRecord

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct OdRecord: Equatable, Hashable

Coarse origin/destination for a trip. Both cells are geohashes of suppressed (mid-trip) positions, so they are already [ProbeConfig::trip_end_suppression_m] away from the true ends.

PropertyTypeDefaultDescription
var originCellStringGeohash cell of the first committed position.
var destCellStringGeohash cell of the last committed position.
var departBucketStringCoarse departure bucket, e.g. tue_am_peak.

Initialisers and methods

  • public init(originCell: String, destCell: String, departBucket: String)
Place

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct Place: Equatable, Hashable

One on-device search result: the matched document's display and context fields plus its position.

PropertyTypeDefaultDescription
var idStringStable identifier (e.g. an OSM-derived id).
var kindPlaceKindWhat kind of entity this is.
var nameStringPrimary display name.
var housenumberString?House number, for [PlaceKind::Address] results.
var streetString?Containing street name, for addresses and POIs.
var localityString?Containing town or city.
var regionString?Containing county / region.
var postcodeString?Postcode, formatted as displayed (e.g. "SW1A 2AA").
var countryCodeStringISO 3166-1 alpha-2 country code (e.g. "GB").
var latDoubleLatitude in decimal degrees (WGS84).
var lonDoubleLongitude in decimal degrees (WGS84).
var categories[String]POI categories (e.g. "fuel", "truck_stop"). Empty for non-POIs.
var importanceFloatRank boost in [0, 1]; larger means more prominent.
var distanceMDouble?Haversine distance in metres from the query's near point, when one was given.

Initialisers and methods

  • public init(id: String, kind: PlaceKind, name: String, housenumber: String?, street: String?, locality: String?, region: String?, postcode: String?, countryCode: String, lat: Double, lon: Double, categories: [String], importance: Float, distanceM: Double?)
ProbeBatch

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct ProbeBatch: Equatable, Hashable

A completed trip's aggregates, ready for the platform layer to POST to the probe ingest endpoint. Contains no trajectory.

PropertyTypeDefaultDescription
var probeFormatUInt32Wire-format version (PROBE_FORMAT).
var territoryString?Territory id the trip was navigated in, when the caller supplies it.
var vehicleClassString?Vehicle costing class (e.g. truck_40t), a class only, never a registration, VIN or driver identifier.
var routeRefString?Opaque token for the served route, so the server can resolve step_index to stable edge / OSM way IDs.
var segments[SegmentAggregate]Per-segment aggregates that cleared suppression and the observation threshold.
var events[ProbeEvent]Coarse, time-bucketed events.
var odOdRecord?Coarse origin/destination, when [ProbeConfig::collect_od] is set and the trip was long enough to have committed positions.

Initialisers and methods

  • public init(probeFormat: UInt32, territory: String?, vehicleClass: String?, routeRef: String?, segments: [SegmentAggregate], events: [ProbeEvent], od: OdRecord?)
ProbeConfig

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct ProbeConfig: Equatable, Hashable

Probe collector configuration, flattened for FFI like [crate::guidance::GuidanceConfig].

Collection is off by default: enabled must be set explicitly (and, in deployment, gated on the fleet customer's opt-in). Everything a batch contains follows from these knobs.

PropertyTypeDefaultDescription
var enabledBoolWhether the collector aggregates at all. When false, ProbeCollector ignores every fix and [ProbeCollector::finish] returns an empty batch.
var tripEndSuppressionMDoubleRadius in metres around both trip ends within which observations are discarded (see the module's trip-end-suppression note).
var minSegmentObservationsUInt32Minimum observation count for a segment cell to appear in the batch.
var timeBucketMinutesUInt32Width of the time-of-day bucket in minutes (the day-of-week prefix is always present); 5 gives the tue_0745-style buckets that line up with the factory's weekly historical-speed profiles.
var odCellPrecisionUInt8Geohash precision (characters) for the origin/destination cells; 5 is roughly a 5 km cell.
var collectOdBoolWhether to emit the coarse origin/destination record at all.

Initialisers and methods

  • public init(enabled: Bool = false, tripEndSuppressionM: Double = Double(500.0), minSegmentObservations: UInt32 = UInt32(1), timeBucketMinutes: UInt32 = UInt32(5), odCellPrecision: UInt8 = UInt8(5), collectOd: Bool = true)
RerouteAnchor

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RerouteAnchor: Equatable, Hashable

The point and course a recalculated route should depart from.

PropertyTypeDefaultDescription
var latDoubleLatitude in decimal degrees (WGS84).
var lonDoubleLongitude in decimal degrees (WGS84).
var courseDegDouble?Course over ground in degrees clockwise from true north, when known. Threaded into the request as the anchor's Valhalla heading.

Initialisers and methods

  • public init(lat: Double, lon: Double, courseDeg: Double?)
RerouteConfig

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RerouteConfig: Equatable, Hashable

Reroute controller configuration, flattened for FFI like [crate::guidance::GuidanceConfig].

Both the count gate and the duration gate must pass for a reroute to be confirmed: a burst of fixes arriving in a fraction of a second should not out-vote the duration requirement, and a slow trickle of fixes should not out-vote the count requirement.

PropertyTypeDefaultDescription
var minConsecutiveOffrouteFixesUInt32Minimum number of consecutive off-route fixes before a reroute is confirmed. A single off-route fix that recovers on the next update (a GPS blip) never reaches this count.
var minOffrouteDurationSDoubleMinimum time in seconds the vehicle must have been continuously off route before a reroute is confirmed.
var minIntervalBetweenReroutesSDoubleMinimum time in seconds between successive reroutes. While inside this window the controller reports [RerouteState::CoolingDown] instead of firing again, the platform is still applying the previous reroute.
var enabledBoolWhether the controller is active at all. When false it always reports [RerouteState::Monitoring] and never confirms a reroute.

Initialisers and methods

  • public init(minConsecutiveOffrouteFixes: UInt32 = UInt32(3), minOffrouteDurationS: Double = Double(5.0), minIntervalBetweenReroutesS: Double = Double(10.0), enabled: Bool = true)
RerouteDecision

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RerouteDecision: Equatable, Hashable

A confirmed reroute: where to route from, where to, and why.

PropertyTypeDefaultDescription
var reasonRerouteReasonWhy the reroute was requested.
var anchorRerouteAnchorThe current position and course to route from.
var waypointsRemaining[RerouteWaypoint]The not-yet-visited waypoints, in visiting order (destination last).

Initialisers and methods

  • public init(reason: RerouteReason, anchor: RerouteAnchor, waypointsRemaining: [RerouteWaypoint])
RerouteWaypoint

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RerouteWaypoint: Equatable, Hashable

One onward waypoint of the active route.

PropertyTypeDefaultDescription
var latDoubleLatitude in decimal degrees (WGS84).
var lonDoubleLongitude in decimal degrees (WGS84).
var isBreakBoolWhether this is a break (leg boundary, with arrival/departure narration) rather than a pass-through via.

Initialisers and methods

  • public init(lat: Double, lon: Double, isBreak: Bool)
RouteManeuver

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RouteManeuver: Equatable, Hashable

One maneuver of the primary route, in SI units with shape indices into [RouteResult::geometry]. Parsed once by the core so integrators never re-parse the raw Valhalla JSON themselves.

PropertyTypeDefaultDescription
var instructionStringWritten instruction, e.g. Turn right onto Main Street.
var maneuverTypeUInt32Numeric Valhalla maneuver type (0–43, exactly as tabulated in the public turn-by-turn API reference: 1–3 start, 4–6 destination, 9–16 turns, 26–27 roundabouts, …).
var verbalPreTransitionInstructionString?Spoken instruction immediately before the transition, when present.
var verbalPostTransitionInstructionString?Spoken instruction immediately after the transition, when present.
var streetNames[String]Street names along the maneuver (empty when unnamed).
var distanceMDoubleManeuver length in metres.
var durationSDoubleEstimated maneuver time in seconds.
var beginShapeIndexUInt32Index into [RouteResult::geometry] where the maneuver starts.
var endShapeIndexUInt32Index into [RouteResult::geometry] where the maneuver ends.
var roundaboutExitCountUInt32?Roundabout exit ordinal, for roundabout maneuvers.

Initialisers and methods

  • public init(instruction: String, maneuverType: UInt32, verbalPreTransitionInstruction: String?, verbalPostTransitionInstruction: String?, streetNames: [String], distanceM: Double, durationS: Double, beginShapeIndex: UInt32, endShapeIndex: UInt32, roundaboutExitCount: UInt32?)
RoutePoint

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RoutePoint: Equatable, Hashable

A route waypoint.

PropertyTypeDefaultDescription
var latDoubleLatitude in decimal degrees (WGS84).
var lonDoubleLongitude in decimal degrees (WGS84).

Initialisers and methods

  • public init(lat: Double, lon: Double)
RouteResult

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RouteResult: Equatable, Hashable

Result of an offline route computation.

PropertyTypeDefaultDescription
var summaryRouteSummarySI summary of the primary route.
var geometry[RoutePoint]The primary route's full geometry (decoded polyline, ordered), ready for a MapLibre LineString. (Defaulted so foreign code that hand-builds records, e.g. test fixtures, stays source-compatible.)
var maneuvers[RouteManeuver]The primary route's maneuvers, flattened across legs, with shape indices into [Self::geometry].
var valhallaResponseJsonStringThe raw Valhalla response JSON (feed this to [GuidanceSession::new]).
var osrmResponseJsonStringOSRM v1 translation at polyline6 precision, for OSRM-speaking consumers (e.g. map matching debug tooling).

Initialisers and methods

  • public init(summary: RouteSummary, geometry: [RoutePoint] = [], maneuvers: [RouteManeuver] = [], valhallaResponseJson: String, osrmResponseJson: String)
RouteSummary

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct RouteSummary: Equatable, Hashable

SI summary of a parsed route.

PropertyTypeDefaultDescription
var distanceMDoubleTotal distance in metres.
var durationSDoubleTotal travel time in seconds.
var hasTollBoolWhether the route crosses a toll.
var hasHighwayBoolWhether the route uses a highway.
var hasFerryBoolWhether the route uses a ferry.

Initialisers and methods

  • public init(distanceM: Double, durationS: Double, hasToll: Bool, hasHighway: Bool, hasFerry: Bool)
SegmentAggregate

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct SegmentAggregate: Equatable, Hashable

One aggregated road segment: statistics for a step_index within the served route, in one day-of-week × time-of-day bucket.

PropertyTypeDefaultDescription
var stepIndexUInt32Zero-based step index within the served route (route_ref).
var todBucketStringDay-of-week × time-of-day bucket, e.g. tue_0745.
var observationsUInt32Number of fixes folded into this cell.
var meanSpeedKmhDoubleMean speed over the cell, in km/h.
var p85SpeedKmhDouble85th-percentile speed over the cell, in km/h (exact up to MAX_SPEED_SAMPLE observations, reservoir-estimated beyond).
var stoppedSDoubleSeconds spent at or below STOPPED_SPEED_MPS in this cell.
var limitDeltaKmhDouble?Mean signed delta between observed speed and the posted limit, in km/h (positive = over the limit). None when no fix in the cell carried a known [SpeedLimit::Known] limit.

Initialisers and methods

  • public init(stepIndex: UInt32, todBucket: String, observations: UInt32, meanSpeedKmh: Double, p85SpeedKmh: Double, stoppedS: Double, limitDeltaKmh: Double?)
SnappedFix

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct SnappedFix: Equatable, Hashable

The route-snapped position for the current update.

This is Ferrostar's snapped_user_location: the raw fix projected onto the route line, with the course snapped to the route direction when [GuidanceConfig::snap_course_to_route] is on (the default). Drive follow-cameras (course-up / chase views) from this, never the raw fix, the raw GPS trace jitters and drifts off the carriageway.

PropertyTypeDefaultDescription
var latDoubleRoute-snapped latitude in decimal degrees (WGS84).
var lonDoubleRoute-snapped longitude in decimal degrees (WGS84).
var courseDegDouble?Course over ground in degrees clockwise from true north, snapped to the route line when course snapping is enabled; None when Ferrostar reports no course for this update.

Initialisers and methods

  • public init(lat: Double, lon: Double, courseDeg: Double?)
SpokenPrompt

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct SpokenPrompt: Equatable, Hashable

The spoken prompt to synthesise for the upcoming maneuver.

PropertyTypeDefaultDescription
var textStringPlain text for the platform text-to-speech engine.
var ssmlString?SSML form, preferred by TTS engines that support it.
var triggerDistanceMDoubleMetres before the maneuver at which to start speaking.
var utteranceIdStringUnique utterance id so platform layers can de-duplicate; the same prompt is reported on every update until it is superseded.

Initialisers and methods

  • public init(text: String, ssml: String?, triggerDistanceM: Double, utteranceId: String)
TerritoryInfo

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct TerritoryInfo: Equatable, Hashable

Summary of one installed territory.

PropertyTypeDefaultDescription
var territoryIdStringStable territory identifier, e.g. "uk".
var displayNameStringHuman-readable territory name.
var versionStringPackage semver.
var dataTimestampStringOSM snapshot timestamp, RFC 3339.
var westDoubleBounding box west edge (degrees).
var southDoubleBounding box south edge (degrees).
var eastDoubleBounding box east edge (degrees).
var northDoubleBounding box north edge (degrees).
var totalBytesUInt64Total size of all layers in the published package, in bytes, whether or not this install holds them.
var installedBytesUInt64Size of the layers this install actually holds, in bytes. Equal to [Self::total_bytes] for a complete install; smaller when layers were deliberately left out. This is the disk figure to show in a storage list.
var omittedKinds[MapLayerKind]Layer kinds the package has and this install deliberately does not hold. Empty for an ordinary complete install. Asking for one of these yields [NavCoreError::LayerNotInstalled].
var pathStringAbsolute path of the installed package directory.
var activeBoolWhether this territory is the active one.

Initialisers and methods

  • public init(territoryId: String, displayName: String, version: String, dataTimestamp: String, west: Double, south: Double, east: Double, north: Double, totalBytes: UInt64, installedBytes: UInt64, omittedKinds: [MapLayerKind], path: String, active: Bool)
UpdatePlan

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct UpdatePlan: Equatable, Hashable

A differential update plan.

PropertyTypeDefaultDescription
var changed[ChangedLayer]Layers that must be downloaded.
var installedBytesUInt64Uncompressed total of the changed layers: the disk the update adds on the device, not the bytes that cross the wire. Layers travel tar + zstd, so this overstates metered transfer for everything except PMTiles (already internally gzipped), do not build a download-cost prompt from it.

Initialisers and methods

  • public init(changed: [ChangedLayer], installedBytes: UInt64)
UpdateResult

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct UpdateResult: Equatable, Hashable

What [TerritoryManager::apply_update] did.

PropertyTypeDefaultDescription
var territoryTerritoryInfoThe territory after the update.
var previousVersionStringThe version that was installed before the update.
var layersFetchedUInt32How many layer blobs were downloaded on this attempt.
var layersReusedUInt32How many changed layers were served from the resumable layer cache, having been fetched and verified by an earlier attempt that failed before it could promote.
var bytesDownloadedUInt64Bytes downloaded on this attempt (compressed blob bytes on the wire, so directly comparable with a metered allowance).

Initialisers and methods

  • public init(territory: TerritoryInfo, previousVersion: String, layersFetched: UInt32, layersReused: UInt32, bytesDownloaded: UInt64)
VisualBanner

Struct · Sources/MapMapKit/Generated/mapmap.swift

swift
public struct VisualBanner: Equatable, Hashable

The visual banner to display for the upcoming maneuver.

PropertyTypeDefaultDescription
var primaryBannerLineMain line: what to do / where you're going.
var secondaryBannerLine?Optional second line.
var subBannerLine?Optional sub banner (typically the lane diagram).
var triggerDistanceMDoubleMetres before the maneuver at which to start displaying.
var drivingSideString?The side of the road traffic drives on at the manoeuvre this banner describes: "left" (UK-style left-hand traffic, where roundabouts circulate clockwise) or "right". None when the engine does not establish it for that manoeuvre: the route translation sets it on roundabout enter/exit and u-turn steps only (see sn_valhalla::translate). Icon mappings read it to pick the roundabout circulation and the u-turn arm, and must draw a plain glyph rather than guess when it is None.
var roadRefString?The route number(s) of the road the manoeuvre this banner describes leads onto, exactly as the engine reports them on that manoeuvre (is_route_number names only, "; " separated, e.g. "A27" or "I 5; US 101"; see sn_valhalla::valhalla::Maneuver::ref_). None when the road carries none or the route came without the gateway's road fields: a road-number badge is drawn only from this, never inferred from a street name.
var countryString?ISO 3166-1 alpha-2 country of that road (e.g. "GB"), from the engine's admin data; picks the country's road-number badge forms.
var subdivisionString?ISO 3166-2 subdivision of that road (e.g. "US-CA", "CA-QC") where the map carries one; some badge tiers apply in one subdivision only.
var roadClassString?Engine road class of that road (motorway, trunk, primary, ...); the GB primary-route badge (green) needs trunk.

Initialisers and methods

  • public init(primary: BannerLine, secondary: BannerLine?, sub: BannerLine?, triggerDistanceM: Double, drivingSide: String? = nil, roadRef: String? = nil, country: String? = nil, subdivision: String? = nil, roadClass: String? = nil)

Enums (MapMap core bindings (generated))

AdrDecision, AdrTunnelCategory, AdrTunnelCode, ChannelInstallOutcome, CostingModel, FetchError, GuidanceUpdate, InstallOutcome, InstructionSeverity, MapLayerKind, NavCoreError, PlaceKind, ProbeEvent, RerouteReason, RerouteState, SpeedLimit, StyleTheme, UpdateOutcome

AdrDecision

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum AdrDecision: Equatable, Hashable

Outcome of a tunnel-entry check, mirroring [sn_adr::Decision].

CaseDescription
allowedPassage is permitted.
blocked(reason: String)Passage is forbidden.
AdrTunnelCategory

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum AdrTunnelCategory: Equatable, Hashable

ADR tunnel category A–E (ascending restrictiveness), mirroring [sn_adr::TunnelCategory].

CaseDescription
aNo dangerous-goods restriction.
bRestriction for goods which may lead to a very large explosion.
c… or a large explosion or large toxic release.
d… or a large fire.
eRestriction for nearly all dangerous goods.
AdrTunnelCode

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum AdrTunnelCode: Equatable, Hashable

ADR 8.6.4 tunnel restriction code of a load, mirroring [sn_adr::TunnelRestrictionCode]. NoCode is ADR's (, ): explicitly unrestricted.

CaseDescription
noCodeADR (, ), passage permitted through all tunnels.
bCode B.
b1000cCode B1000C.
bdCode B/D.
beCode B/E.
cCode C.
c5000dCode C5000D.
cdCode C/D.
ceCode C/E.
dCode D.
deCode D/E.
eCode E.
ChannelInstallOutcome

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum ChannelInstallOutcome: Equatable, Hashable

How a channel install ended.

CaseDescription
installed(result: ChannelInstallResult)The package verified and was promoted.
cancelledThe CancelToken was tripped before promotion. Nothing was installed; verified layers stay parked for the next attempt.
CostingModel

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum CostingModel: Equatable, Hashable

Valhalla costing model, mirroring [sn_valhalla::valhalla::Costing].

CaseDescription
autoStandard car costing.
truckTruck costing (required when an ADR profile is supplied).
busBus costing.
motorScooterMotor scooter costing.
motorcycleMotorcycle costing.
bicycleBicycle costing.
pedestrianPedestrian costing.
FetchError

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum FetchError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError

A transport failure thrown by a foreign LayerFetcher implementation.

PropertyTypeDefaultDescription
var errorDescriptionString?Human-readable description of the failure.
CaseDescription
Transport(message: String)The download failed (network, storage, cancelled, …).
GuidanceUpdate

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum GuidanceUpdate: Equatable, Hashable

The guidance state reported after each location update, flattened for FFI from Ferrostar's TripState.

The Navigating variant is deliberately larger than the others: it is the steady-state payload and the FFI shape (UniFFI enums cannot box), and one allocation per location fix is irrelevant next to the fix cadence.

CaseDescription
navigating(stepIndex: UInt32, distanceToNextManeuverM: Double, distanceRemainingM: Double, durationRemainingS: Double, currentInstruction: String, deviationM: Double?, visual: VisualBanner?, spoken: SpokenPrompt?, snapped: SnappedFix?, severity: InstructionSeverity, speedLimit: SpeedLimit?)Actively navigating.
arrivedThe user has arrived at the destination.
offRoute(deviationM: Double)The user has left the route entirely (beyond the configured deviation threshold from every remaining step). The platform layer should recalculate.
InstallOutcome

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum InstallOutcome: Equatable, Hashable

How a cancellable install ended.

CaseDescription
installed(territory: TerritoryInfo)The package verified and was promoted.
cancelledThe CancelToken was tripped before promotion. Nothing was installed; staging was removed.
InstructionSeverity

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum InstructionSeverity: Equatable, Hashable

How urgently a guidance update should be surfaced to the driver.

Voice layers map this to prosody (pitch/rate) and earcons; visual layers to banner styling. Ordered: Info < Warning < Critical.

Derivation (single source of truth for every SDK):

  • Critical, restriction prohibitions: an ADR tunnel prohibition ([InstructionSeverity::for_adr_decision] on a Blocked decision, the hook platform layers use when check_tunnel fires off-route) and manoeuvres crossing a gate (a physical barrier the vehicle must not run).
  • Warning, approaching a restriction or interruption of the drive: toll booths and ferry boardings/landings.
  • Info, every normal manoeuvre.

Off-route updates carry no instruction; platform voice layers treat [GuidanceUpdate::OffRoute] itself as Warning.

CaseDescription
infoA normal manoeuvre announcement.
warningApproaching a restriction (toll booth, ferry boarding/landing).
criticalA prohibition: ADR tunnel block or a gate across the carriageway.
MapLayerKind

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum MapLayerKind: Equatable, Hashable

Map layer kind, mirroring [sn_package::LayerKind].

CaseDescription
valhallaTilesValhalla routing tile tree.
pmtilesPMTiles render layer.
geocodeIndexTantivy geocoding index.
poiSidecarProprietary POI sidecar database.
extra(name: String)Any other layer kind, by its manifest string.

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum NavCoreError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError

The flat error type crossing the FFI boundary.

Rich typed errors live on the Rust side (TerritoryError, RoutingError, GuidanceError); foreign code gets a stable category plus a human-readable message.

PropertyTypeDefaultDescription
var errorDescriptionString?Human-readable description.
CaseDescription
Territory(message: String)Territory storage or lifecycle failure.
Verification(message: String)A package failed cryptographic or integrity verification.
Routing(message: String)Route request building or response parsing failure (including Valhalla error bodies from the on-device engine).
Guidance(message: String)Guidance session failure.
InvalidArgument(message: String)A caller-supplied argument was invalid.
Search(message: String)On-device geocode search failure (index missing, unreadable or of an unsupported schema version).
LayerNotInstalled(territoryId: String, kind: String, detail: String)The territory has a layer of that kind, but this install left it out (see [TerritoryManager::install_from_channel]). Its own case on purpose: it is not Territory (nothing failed), not a corrupt install and not an unknown territory. The app knows what it chose not to download, so this is the signal to offer the download, not to report an error. The human-readable sentence is detail, not message: a UniFFI error variant with several fields, one of them named message, generates a Kotlin class whose constructor property collides with Throwable.message and does not compile. Single-field variants (every other case here) are fine.
PlaceKind

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum PlaceKind: Equatable, Hashable

The kind of entity a Place describes, mirroring [sn_geocode::DocKind].

CaseDescription
addressA single addressable building or unit (housenumber + street).
streetA named street or road.
localityA town, city, village or suburb.
poiA point of interest (fuel station, truck stop, museum, …).
postcodeA postcode centroid (full or outward code).
ProbeEvent

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum ProbeEvent: Equatable, Hashable

A coarse, time-bucketed event within a trip.

CaseDescription
offRoute(todBucket: String, deviationBandM: UInt32)The vehicle left the route (a confirmed off-route condition from guidance). Carries only the time bucket and a coarse deviation band.
etaOutcome(predictedS: Double, actualS: Double, routeLenKmBucket: String)The realised trip duration against the engine's first estimate. Feeds ETA-accuracy calibration; carries no location.
RerouteReason

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum RerouteReason: Equatable, Hashable

Why a reroute was requested.

CaseDescription
offRoute(deviationM: Double)The vehicle left the route line; deviation_m is the distance from the route at the confirming fix.
fasterRoute(savesS: UInt32)A periodic re-evaluation found a faster route for the remaining journey (see [crate::faster_route::FasterRouteEvaluator]); the driver accepted the switch. saves_s is the estimated saving in seconds versus staying on the current route.
RerouteState

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum RerouteState: Equatable, Hashable

The controller's state after the most recent update, for UI and telemetry.

CaseDescription
monitoringOn route (or recovered): nothing to do.
offRouteSuspected(count: UInt32)Off route, but not yet confirmed, the count and/or duration gate has not been met. count is the run of consecutive off-route fixes so far.
rerouteNeededA reroute is confirmed for this update; the accompanying RerouteDecision should be routed. Reported exactly once per confirmed departure.
coolingDownOff route and confirmed again, but suppressed because a reroute fired within [RerouteConfig::min_interval_between_reroutes_s].
SpeedLimit

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum SpeedLimit: Equatable, Hashable

The posted speed limit for the current edge, for a speed-limit badge and over-limit warnings.

This is surfaced from the OSRM annotation.maxspeed that Ferrostar threads through its navigation state (TripState::Navigating.annotation_json) at the current geometry index, in the Mapbox shape (https://docs.mapbox.com/api/navigation/directions/#route-leg-object). It appears only when the route actually carries speed-limit data: on-device that means the Valhalla graph was built with OSM maxspeed (and admin data for implicit limits) and the engine emitted per-maneuver limits, which the translator forwarded (see [sn_valhalla::valhalla::SpeedLimit]). With stock data there is no annotation and [GuidanceUpdate::Navigating] reports no limit at all, values are never invented.

CaseDescription
known(kmh: Double)A known posted limit, normalised to kilometres per hour regardless of the unit the route expressed it in.
unlimitedThe road is de-restricted (Mapbox maxspeed none; OSM maxspeed=none, e.g. a German autobahn), show a "no limit" badge, do not warn.
unknownA limit applies but is unknown for the current segment (Mapbox maxspeed unknown), the data source annotates this position but has no value for it. Distinct from the field being absent entirely.
StyleTheme

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum StyleTheme: Equatable, Hashable

Which packaged style variant [TerritoryManager::territory_style] returns, mirroring [crate::territory::StyleTheme] (and the web SDK's buildStyle({ theme }) names).

CaseDescription
lightThe light (day) style, also the package default.
darkThe dark (night) style.
UpdateOutcome

Enum · Sources/MapMapKit/Generated/mapmap.swift

swift
public enum UpdateOutcome: Equatable, Hashable

How a cancellable update ended.

CaseDescription
applied(result: UpdateResult)The update verified and was swapped in.
cancelledThe CancelToken was tripped before promotion. The installed version is untouched; verified layers stay parked for a retry.

Protocols (MapMap core bindings (generated))

CancelTokenProtocol, GuidanceSessionProtocol, LayerFetcher, LocalRouter, ProbeCollectorProtocol, TerritoryManagerProtocol, TerritorySearchProtocol

CancelTokenProtocol

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol CancelTokenProtocol: AnyObject, Sendable

A cancellation handle for an in-flight territory install or update.

The install calls on TerritoryManager block the calling thread for as long as a multi-gigabyte package takes to download, unpack and verify. Create a token, pass it to one of the _cancellable variants running on a background thread, and call [CancelToken::cancel] from the UI thread when the user taps Cancel. The install polls it at safe points and returns [InstallOutcome::Cancelled] / [UpdateOutcome::Cancelled] with its staging directory removed: no partial package is left on disk, the previously installed version is untouched, and layers that had already been verified stay in the resumable cache for the next attempt. Cancelling after the call has returned changes nothing.

The token cannot interrupt a LayerFetcher blocked in a transfer: give the fetcher the same token and have it poll [CancelToken::is_cancelled] between chunks (or abort its request when the app cancels). Whatever the fetcher then returns, the install reports Cancelled, not a transport error.

Initialisers and methods

  • func cancel(): Request cancellation. Idempotent and safe from any thread.
  • func isCancelled() -> Bool: Whether [Self::cancel] has been called.
GuidanceSessionProtocol

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol GuidanceSessionProtocol: AnyObject, Sendable

A turn-by-turn guidance session (see [crate::guidance]).

Thread-safe: the mutable Ferrostar navigation state is guarded by a mutex, matching UniFFI's shared-object concurrency model.

Initialisers and methods

  • func advanceToNextStep() throws -> GuidanceUpdate: Manually advance to the next step (e.g. in a tunnel with no GNSS).
  • func totalSteps() -> UInt32: Number of steps in the route, including the arrival step.
  • func updateLocation(lat: Double, lon: Double, timestampMs: Int64, speedMps: Double?, courseDeg: Double?, horizontalAccuracyM: Double?) throws -> GuidanceUpdate: Feed a location fix; returns the updated guidance state. horizontal_accuracy_m defaults to 0.0 (trusted exactly) when absent; pass the platform's reported accuracy when available so step advance and deviation gating behave correctly.
LayerFetcher

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol LayerFetcher: AnyObject, Sendable

The platform's download transport for over-the-air territory updates, exported as a UniFFI callback interface like [crate::routing::LocalRouter]: the core decides what to fetch and cryptographically verifies everything; Kotlin/Swift decide how bytes move (OkHttp, URLSession, an air-gapped mirror, …).

Initialisers and methods

  • func fetch(relPath: String, expectedBlake3: String, destPath: String) throws: Download the channel-relative rel_path (e.g. territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local file dest_path. expected_blake3 is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouter

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol LocalRouter: AnyObject, Sendable

The injection point for the platform's on-device Valhalla binding.

valhalla-mobile (https://github.com/Rallista/valhalla-mobile) exposes a route(request_json) -> response_json actor on both Android and iOS; Kotlin/Swift implement this interface with that actor and pass it to [crate::ffi::route_offline]. Exported as a UniFFI callback interface (with_foreign) so the implementation lives in foreign code.

Initialisers and methods

  • func route(requestJson: String) -> String: Execute a Valhalla turn-by-turn request and return the raw response JSON (either a route response or a Valhalla error body).
ProbeCollectorProtocol

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol ProbeCollectorProtocol: AnyObject, Sendable

On-device probe collector. Feed it every guidance update with the fix's position, speed and timestamp; call finish at arrival or trip abandonment to get the ProbeBatch to upload.

Interior mutability (a Mutex) lets the FFI methods take &self, matching the [crate::guidance::GuidanceSession] object shape.

Initialisers and methods

  • func finish(arrived: Bool, timestampMs: Int64) -> ProbeBatch: Close the trip and return the batch to upload. arrived distinguishes a completed trip from an abandoned one (both apply end suppression).
  • func finishJson(arrived: Bool, timestampMs: Int64) -> String?: Close the trip and return the exact JSON body to POST /v1/probe, or None when the batch carries nothing worth uploading. This is the single canonical serialiser for the probe wire format, platform code should upload this verbatim rather than re-encoding the record, so the wire form can never drift from what the gateway ingests.
  • func observe(update: GuidanceUpdate, fixLat: Double, fixLon: Double, speedMps: Double?, timestampMs: Int64): Feed one guidance update and its fix. speed_mps is the device's reported ground speed when available (preferred); pass None to let the collector estimate it from successive positions.
  • func setRouteRef(routeRef: String): Set the opaque served-route token so the server can resolve segments.
  • func setTerritory(territory: String): Set the territory id stamped into the batch.
  • func setVehicleClass(vehicleClass: String): Set the vehicle costing class stamped into the batch (a class only, never a vehicle or driver identifier).
TerritoryManagerProtocol

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol TerritoryManagerProtocol: AnyObject, Sendable

Manages signed offline territory packages (see [crate::territory]).

Initialisers and methods

  • func active() throws -> String?: The active territory id, if one is set and still installed.
  • func applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher) throws -> UpdateResult: Apply a differential update: stage, fetch only the changed layers through fetcher, verify everything and swap atomically. Any failure leaves the installed territory untouched; the active flag is preserved. Blocks until done and cannot be interrupted; see [Self::apply_update_cancellable].
  • func applyUpdateCancellable(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken) throws -> UpdateOutcome: [Self::apply_update] with a CancelToken. Polled before every layer download, between archive entries while unpacking, before each hash pass and before promotion. A tripped token yields [UpdateOutcome::Cancelled]: the installed version is untouched, staging is removed, and layers that had already been fetched and verified stay in the resumable cache, so calling again with the same manifest re-fetches only what is missing. Give fetcher the same token so it can stop an in-flight transfer (the token cannot interrupt foreign code on its own); whatever the fetcher then returns, a tripped token reports Cancelled rather than a transport error.
  • func cachedLayerBytes() throws -> UInt64: Bytes parked in the resumable layer cache: downloads a failed install already paid for, which a retry will not pay for again. Surface this next to a "resume" affordance and in storage settings.
  • func checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher) throws -> AvailableUpdate?: Check the signed channel index for an update to an installed territory. index_json must be the exact bytes served as index.json and index_sig_base64 the content of index.json.sig; the remote manifest is fetched and verified through fetcher. Returns None when the device is already on the channel's latest version (or the channel does not list the territory).
  • func clearLayerCache() throws: Discard every parked layer. The bytes are lost and a later install re-downloads (and on a metered channel re-pays for) them, so offer this only as a deliberate "free up space" action.
  • func installDir(packageDir: String) throws -> TerritoryInfo: Install an unpacked package directory. Blocks until done and cannot be interrupted; see [Self::install_dir_cancellable].
  • func installDirCancellable(packageDir: String, cancel: CancelToken) throws -> InstallOutcome: [Self::install_dir] with a CancelToken. Polled between copied files, before verification and before promotion.
  • func installDirPartial(packageDir: String, omit: [MapLayerKind], cancel: CancelToken) throws -> InstallOutcome: Install an unpacked package directory, holding only the layers this app can use: omit names the kinds to leave out (e.g. Pmtiles and Extra("style") for an app with no map view). The install records what it left out, and every later verification requires those layers to be absent rather than exempting them from hashing, so the record cannot be forged into admitting tampered bytes. Asking for an omitted layer answers [NavCoreError::LayerNotInstalled], which is not an error state: it is "you chose not to download this". The selection is sticky: updates carry it forward, so an app that skipped the render layers never downloads them on an update either.
  • func installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, omit: [MapLayerKind], fetcher: LayerFetcher, cancel: CancelToken) throws -> ChannelInstallOutcome: Install a territory from the channel, downloading only the layers this app can use. The first-install counterpart of [Self::apply_update], and the only path on which omitting layers saves bandwidth: a layer in omit is never requested, so it is never metered and never stored. index_json / index_sig_base64 are the exact served bytes of index.json and index.json.sig; the channel's latest version of the territory is installed. Nothing is trusted but the pinned key: the index signature, the manifest signature and every blob's BLAKE3 are checked, and the assembled directory goes through the same full verification pass as any other install before it is promoted. Interrupted installs resume: verified layers stay parked in the layer cache. Calling it again for a territory that is already installed is how a selection is widened later. Layers already on the device at the same content hash are linked, not re-downloaded, so adding the map to a router-only install costs the map alone.
  • func installSnpkg(archivePath: String) throws -> TerritoryInfo: Install a packed .snpkg archive (verify-then-promote; rejected packages leave no trace). Blocks until done and cannot be interrupted; see [Self::install_snpkg_cancellable].
  • func installSnpkgCancellable(archivePath: String, cancel: CancelToken) throws -> InstallOutcome: [Self::install_snpkg] with a CancelToken. Polled between archive entries, before verification and before promotion; a tripped token yields [InstallOutcome::Cancelled] with staging removed and nothing installed.
  • func installSnpkgPartial(archivePath: String, omit: [MapLayerKind], cancel: CancelToken) throws -> InstallOutcome: [Self::install_dir_partial] from a packed .snpkg archive. The archive carries every layer, so this saves storage, not bandwidth: the omitted layers are unpacked and then dropped before verification. For the bandwidth saving use [Self::install_from_channel], which never fetches a blob it does not want.
  • func layerPath(territoryId: String, kind: MapLayerKind) throws -> String: Absolute path of a layer inside an installed territory (e.g. the Valhalla tile tree for valhalla-mobile, the PMTiles file for MapLibre).
  • func list() throws -> [TerritoryInfo]: List installed territories in territory-id order.
  • func openSearch(territoryId: String) throws -> TerritorySearch: Open the installed territory's bundled geocode index for on-device search. The returned TerritorySearch holds the index open (mmap-backed), create it once per territory and reuse it across queries.
  • func planUpdate(newManifestJson: String) throws -> UpdatePlan: Plan a differential update from the installed manifest to new_manifest_json (a signed manifest's JSON body, as served by the update channel).
  • func remove(territoryId: String) throws: Remove an installed territory (clears the active marker if needed).
  • func setActive(territoryId: String) throws: Mark a territory as active (persisted atomically).
  • func territoryStyle(territoryId: String, theme: StyleTheme) throws -> String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK's buildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via a pmtiles://<absolute path> URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly over the package's PMTiles layer. The glyphs endpoint stays hosted (MapLibre caches fetched glyph ranges; no offline glyph bundle ships in packages today).
  • func verifyTerritory(territoryId: String) throws -> TerritoryInfo: Re-verify an installed territory from disk: the manifest signature, the BLAKE3 of every layer this install holds, and the absence of every layer it recorded as omitted. The ordinary calls do not re-hash gigabytes; this is the on-demand integrity check for after a restore or a crash. A failure arrives as [NavCoreError::Verification] and means the install must be repaired or reinstalled, not retried.
TerritorySearchProtocol

Protocol · Sources/MapMapKit/Generated/mapmap.swift

swift
public protocol TerritorySearchProtocol: AnyObject, Sendable

On-device search over an installed territory's bundled geocode index (see [TerritoryManager::open_search]). Fully offline; queries are synchronous and mmap-backed, call from a background thread/dispatcher like any other disk-bound SDK call.

Initialisers and methods

  • func reverse(lat: Double, lon: Double, limit: UInt32) throws -> [Place]: Reverse geocode: the nearest indexed places to a coordinate, nearest first.
  • func search(query: String, near: RoutePoint?, limit: UInt32) throws -> [Place]: Free-text search (addresses, streets, places, POIs, UK postcodes; prefix-tokenised, so it works for search-as-you-type). near biases ranking towards the given point and fills each result's distance_m; limit caps the number of hits.

Functions (MapMap core bindings (generated))

buildOfflineRouteRequest, checkTunnel, forbiddenCategories, parseRouteResult, routeOffline, styleForNavigation, styleWithBuildings3d

buildOfflineRouteRequest

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func buildOfflineRouteRequest(locations: [RoutePoint], costing: CostingModel, adr: AdrProfile?) throws -> String

Build the Valhalla request JSON an on-device engine accepts, with ADR costing options merged (conflicts rejected). Useful when foreign code wants to drive the engine itself.

checkTunnel

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func checkTunnel(profile: AdrProfile, category: AdrTunnelCategory) -> AdrDecision

Decide whether the vehicle may pass through a tunnel of category (conservative ADR 8.6.4 reading; see [crate::adr::check_tunnel]).

forbiddenCategories

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func forbiddenCategories(profile: AdrProfile) -> [AdrTunnelCategory]

All tunnel categories the vehicle is forbidden from (ascending). Empty when unrestricted.

parseRouteResult

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func parseRouteResult(responseJson: String) throws -> RouteResult

Parse a raw on-device route response into a RouteResult, including the typed [RouteResult::geometry] and [RouteResult::maneuvers].

routeOffline

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func routeOffline(router: LocalRouter, locations: [RoutePoint], costing: CostingModel, adr: AdrProfile?) throws -> RouteResult

Full offline routing orchestration: build the request, run it through the injected LocalRouter (the platform's valhalla-mobile binding) and parse the response.

styleForNavigation

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func styleForNavigation(styleJson: String, keepBuildings3d: Bool = true) throws -> String

Prepares a style for a turn-by-turn navigation view. Call it on whatever style the app otherwise uses, right before loading the navigation map; it is where nav-view safeguards live.

By default (keep_buildings_3d = true) the style's 3D building state is left exactly as the app configured it: MapLibre Native's historical fill-extrusion memory blow-up (maplibre-native#4107) is fixed by the instancing rework (#4256; Android >= 13.2.0, iOS >= 6.26.1), and a navigation-loop soak (qa/expo-3d-soak, 17 Jul 2026) measured a bounded ~170 MB for city-wide 3D at nav zoom, flat, no growth.

Pass keep_buildings_3d = false to strip the building-3d layer, the pre-fix behaviour, when targeting MapLibre pins older than the fix or low-memory devices you have not measured.

styleWithBuildings3d

Function · Sources/MapMapKit/Generated/mapmap.swift

swift
public func styleWithBuildings3d(styleJson: String, enabled: Bool) throws -> String

Toggle 3D building extrusions on a MapMap style.json document (a territory package's baked style or a hosted style body), returning the adjusted document to load into MapLibre. Idempotent; errors with [NavCoreError::InvalidArgument] on non-style input.

Safe on MapLibre Native releases carrying the fill-extrusion instancing fix (maplibre-native#4256, merged 2026-05-05: Android

= 13.2.0, iOS >= 6.26.1), the historical street-zoom memory blow-up (#4107, 900 MB+ at zoom 17) is fixed there. Measured 17 Jul 2026 on a Pixel-class device (qa/expo-3d-soak): city-wide extrusions at zoom 16.5/pitch 60 cost a bounded ~170 MB over an identical no-3D control, flat over the soak. On pins older than the fix, keep this off outside measured map-browsing views.

Ferrostar bindings (generated)

Classes (Ferrostar bindings (generated))

AndAdvanceConditions, DistanceEntryAndExitCondition, DistanceEntryAndSnappedExitCondition, DistanceFromStepCondition, DistanceToEndOfStepCondition, ManualStepCondition, NavigationCacheImpl, NavigationController, NavigationObserverImpl, NavigationRecorder, NavigationReplay, NavigationSession, NavigationSessionCache, Navigator, OrAdvanceConditions, RouteAdapter, RouteDeviationDetectorImpl, RouteRequestGeneratorImpl, RouteResponseParserImpl, StepAdvanceCondition

AndAdvanceConditions

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class AndAdvanceConditions: AndAdvanceConditionsProtocol, @unchecked Sendable

Advance if all of the conditions are met (AND).

DistanceEntryAndExitCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class DistanceEntryAndExitCondition: DistanceEntryAndExitConditionProtocol, @unchecked Sendable

A stateful condition that requires the user to reach the end of the step then proceed past it to advance.

DistanceEntryAndSnappedExitCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class DistanceEntryAndSnappedExitCondition: DistanceEntryAndSnappedExitConditionProtocol, @unchecked Sendable

A stateful condition that requires the user to reach the end of the step then proceed past it to advance.

This variant uses route snapping (snapping to the combined current+next step geometry) for the exit check, making it more robust for pedestrian/hiking navigation where users may walk on the opposite side of the street or wander around the optimal path. The route-snapped exit check prevents premature advancement while still allowing natural pedestrian movement patterns. The exit distance is measured from the current step to the route-snapped position.

DistanceFromStepCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class DistanceFromStepCondition: DistanceFromStepConditionProtocol, @unchecked Sendable

Advances once the user is at least [Self::distance] meters from the current step's polyline.

This results in delayed advance, but is more robust to spurious / unwanted step changes in scenarios including self-intersecting routes (sudden jumps to the next step) and pauses at intersections (advancing too soon before the maneuver is complete).

NOTE! This may be less robust to things like short steps, out-and-backs, and U-turns, where this may eagerly exit a current step before the user has traversed it if the start of the step is within range of the end.

DistanceToEndOfStepCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class DistanceToEndOfStepCondition: DistanceToEndOfStepConditionProtocol, @unchecked Sendable

Automatically advances when the user's location is close enough to the end of the step.

This results in an eager advance where the user will jump to the next step when the condition is met.

ManualStepCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class ManualStepCondition: ManualStepConditionProtocol, @unchecked Sendable

Never advances to the next step automatically; requires calling NavigationController::advance_to_next_step.

You can use this to implement custom behaviors in external code.

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationCacheImpl: NavigationCache, @unchecked Sendable

Initialisers and methods

  • open func save(record: Data)
  • open func load() -> Data?
  • open func delete()

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationController: NavigationControllerProtocol, @unchecked Sendable

Manages the navigation lifecycle through a route, returning an updated state given inputs like user location.

Notes for implementing a new platform:

  • A controller is bound to a single route; if you want recalculation, create a new instance.
  • This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state.

Initialisers and methods

  • public convenience init(route: Route, config: NavigationControllerConfig): Create a navigation controller for a route and configuration.

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationObserverImpl: NavigationObserver, @unchecked Sendable

Initialisers and methods

  • open func onGetInitialState(state: NavState)
  • open func onUserLocationUpdate(location: UserLocation, state: NavState)
  • open func onAdvanceToNextStep(state: NavState)
  • open func onRouteAvailable(route: Route)

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationRecorder: NavigationRecorderProtocol, @unchecked Sendable

Initialisers and methods

  • public convenience init(route: Route, config: NavigationControllerConfig)
  • open func getEvents() -> [NavigationRecordingEvent]
  • open func getRecordingJson() throws -> String
  • open func onAdvanceToNextStep(state: NavState)
  • open func onGetInitialState(state: NavState)
  • open func onRouteAvailable(route: Route)
  • open func onUserLocationUpdate(location: UserLocation, state: NavState)

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationReplay: NavigationReplayProtocol, @unchecked Sendable

A wrapper around NavigationRecording to facilitate replaying the event stream.

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationSession: NavigationSessionProtocol, @unchecked Sendable

Initialisers and methods

  • public convenience init(controller: Navigator, observers: [NavigationObserver])
  • open func advanceToNextStep(state: NavState) -> NavState
  • open func getInitialState(location: UserLocation) -> NavState
  • open func route() -> Route
  • open func updateUserLocation(location: UserLocation, state: NavState) -> NavState

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class NavigationSessionCache: NavigationSessionCacheProtocol, @unchecked Sendable

Initialisers and methods

  • public convenience init(config: NavigationCachingConfig, cache: NavigationCache)
  • open func canResume() -> Bool: Check if the navigation session can be resumed.
  • open func load() -> NavigationSessionSnapshot?: Load the navigation session record from the cache if it exists and is not stale.
  • open func onAdvanceToNextStep(state: NavState)
  • open func onGetInitialState(state: NavState)
  • open func onRouteAvailable(route: Route)
  • open func onUserLocationUpdate(location: UserLocation, state: NavState)

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class Navigator: NavigatorProtocol, @unchecked Sendable

Core interface for navigation functionalities.

This trait defines the essential operations for a navigation state manager. This lets us build additional layers (e.g. event logging) around NavigationController in a composable manner.

Initialisers and methods

  • open func route() -> Route
  • open func getInitialState(location: UserLocation) -> NavState
  • open func advanceToNextStep(state: NavState) -> NavState
  • open func updateUserLocation(location: UserLocation, state: NavState) -> NavState
OrAdvanceConditions

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class OrAdvanceConditions: OrAdvanceConditionsProtocol, @unchecked Sendable

Advance if any of the conditions are met (OR).

This is ideal for short circuit type advance conditions.

E.g. you may have:

  1. A short circuit detecting if the user has exceeded a large distance from the current step.
  2. A default advance behavior.
RouteAdapter

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class RouteAdapter: RouteAdapterProtocol, @unchecked Sendable

The route adapter bridges between the common core and a routing backend where interaction takes place over a generic request/response flow (typically over a network; local/offline routers do not use this object as the interaction patterns are different).

This is essentially the composite of the RouteRequestGenerator and RouteResponseParser traits, but it provides one further level of abstraction which is helpful to consumers. As there is no way to signal compatibility between request generators and response parsers, the RouteAdapter provides convenience constructors which take the guesswork out of it, while still leaving consumers free to implement one or both halves.

In the future, we may provide additional methods or conveniences, and this indirection leaves the design open to such changes without necessarily breaking source compatibility. One such possible extension would be the ability to fetch more detailed attributes in real time. This is supported by the Valhalla stack, among others.

Ideas welcome re: how to signal compatibility between request generators and response parsers. I don't think we can do this in the type system, since one of the reasons for the split design is modularity, including the possibility of user-provided implementations, and these will not always be of a "known" type to the Rust side.

Initialisers and methods

  • public convenience init(requestGenerator: RouteRequestGenerator, responseParser: RouteResponseParser): Creates a route adapter from any request generator and response parser. This constructor offers unlimited flexibility, but if you're using a major routing vendor API, [RouteAdapter::from_well_known_route_provider] may be a more convenient interface.
  • public static func fromWellKnownRouteProvider(wellKnownRouteProvider: WellKnownRouteProvider) throws -> RouteAdapter: Creates a route adapter from a well-known provider configuration.
  • open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest
  • open func parseResponse(response: Data) throws -> [Route]
RouteDeviationDetectorImpl

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class RouteDeviationDetectorImpl: RouteDeviationDetector, @unchecked Sendable

A custom deviation detector (for extending the behavior of RouteDeviationTracking).

This allows for arbitrarily complex implementations when the provided ones are not enough. For example, detecting that the user is proceeding the wrong direction by keeping a ring buffer of recent locations, or perform local map matching.

Initialisers and methods

  • open func checkRouteDeviation(route: Route, tripState: TripState) -> RouteDeviation: Determines whether the user is following the route correctly or not. NOTE: This function has a single responsibility. Side-effects like whether to recalculate a route are left to higher levels, and implementations should only be concerned with determining the facts. IMPORTANT: If you are short circuiting StepAdvanceCondition's to allow skipping steps, you must always fall back to checking the deviation from the full route line.
RouteRequestGeneratorImpl

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class RouteRequestGeneratorImpl: RouteRequestGenerator, @unchecked Sendable

A trait describing any object capable of generating RouteRequests.

The interface is intentionally generic. Every routing backend has its own set of parameters, including a "profile," max travel speed, units of speed and distance, and more. It is assumed that these properties will be set at construction time or otherwise configured before use, so that we can keep the public interface as generic as possible.

Implementations may be either in Rust (most popular engines should eventually have Rust glue code) or foreign code.

Initialisers and methods

  • open func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest: Generates a routing backend request given the set of locations. While most implementations will treat the locations as an ordered sequence, this is not guaranteed (ex: an optimized router).
RouteResponseParserImpl

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class RouteResponseParserImpl: RouteResponseParser, @unchecked Sendable

A generic interface describing any object capable of parsing a response from a routing backend into one or more Routes.

Initialisers and methods

  • open func parseResponse(response: Data) throws -> [Route]: Parses a raw response from the routing backend into a route. We use a sequence of octets as a common interchange format. as this works for all currently conceivable formats (JSON, PBF, etc.).
StepAdvanceCondition

Class · Sources/MapMapKit/Generated/ferrostar.swift

swift
open class StepAdvanceCondition: StepAdvanceConditionProtocol, @unchecked Sendable

When implementing custom step advance logic, this trait allows you to define whether the condition should advance to the next condition, the next step or not.

At the moment, these must be implemented in Rust.

Initialisers and methods

  • open func shouldAdvanceStep(tripState: TripState) -> StepAdvanceResult: This callback method is used by a step advance condition to receive step updates. The step advance condition can choose based on its outcome and internal state whether to advance to the next step or not.
  • open func newInstance() -> StepAdvanceCondition: Creates a clean instance of this condition with the same configuration but reset state. This is used by composite conditions (Or/And) to ensure proper state isolation when any condition triggers advancement. Implementation Requirements: - Stateless conditions: Return a copy/clone of self - Stateful conditions: Return a new instance with initial state but preserve configuration parameters - Composite conditions: Recursively create fresh instances of all nested conditions This method prevents the state leakage bugs that can cause rapid step advancement and jumping behavior in navigation.

Structs (Ferrostar bindings (generated))

BoundingBox, Congestion, CourseOverGround, GeographicCoordinate, Heading, Incident, LaneInfo, LocationSimulationState, NavigationCachingConfig, NavigationControllerConfig, NavigationRecordingEvent, NavigationSessionSnapshot, NavState, OsrmWaypointProperties, Route, RouteStep, SerializableNavState, Speed, SpokenInstruction, StepAdvanceResult, TripProgress, TripSummary, UserLocation, ValhallaLocationSearchFilter, ValhallaWaypointProperties, VisualInstruction, VisualInstructionContent, Waypoint

BoundingBox

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct BoundingBox: Equatable, Hashable, Codable

A geographic bounding box defined by its corners.

PropertyTypeDefaultDescription
var swGeographicCoordinateThe southwest corner of the bounding box.
var neGeographicCoordinateThe northeast corner of the bounding box.

Initialisers and methods

  • public init(sw: GeographicCoordinate, ne: GeographicCoordinate)
Congestion

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Congestion: Equatable, Hashable, Codable

Details about congestion for an incident.

PropertyTypeDefaultDescription
var valueUInt8The level of congestion caused by the incident. 0 = no congestion 100 = road closed Other values mean no congestion was calculated

Initialisers and methods

  • public init(value: UInt8)
CourseOverGround

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct CourseOverGround: Equatable, Hashable, Codable

The direction in which the user/device is observed to be traveling.

PropertyTypeDefaultDescription
var degreesUInt16The direction in which the user's device is traveling, measured in clockwise degrees from true north (N = 0, E = 90, S = 180, W = 270).
var accuracyUInt16?The accuracy of the course value, measured in degrees.

Initialisers and methods

  • public init(degrees: UInt16, accuracy: UInt16?)
GeographicCoordinate

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct GeographicCoordinate: Equatable, Hashable, Codable

A geographic coordinate in WGS84.

PropertyTypeDefaultDescription
var latDoubleThe latitude (in degrees).
var lngDoubleThe Longitude (in degrees).

Initialisers and methods

  • public init(lat: Double, lng: Double)
Heading

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Heading: Equatable, Hashable, Codable

The heading of the user/device.

PropertyTypeDefaultDescription
var trueHeadingUInt16The heading in degrees relative to true north.
var accuracyUInt16The platform specific accuracy of the heading value.
var timestampDateThe time at which the heading was recorded.

Initialisers and methods

  • public init(trueHeading: UInt16, accuracy: UInt16, timestamp: Date)
Incident

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Incident: Equatable, Hashable, Codable

An incident affecting the free flow of traffic, such as constructions, accidents, and congestion.

PropertyTypeDefaultDescription
var idStringA unique identifier for the incident.
var incidentTypeIncidentTypeThe type of incident.
var descriptionString?A short description of the incident.
var longDescriptionString?A longer description of the incident.
var creationTimeUtcDateTime?The time at which the incident was last created. NB: This can change throughout the life of the incident.
var startTimeUtcDateTime?The time at which the incident started or is expected to start (ex: planned closure).
var endTimeUtcDateTime?The time at which the incident ended or is expected to end.
var impactImpact?The level of impact to traffic.
var lanesBlocked[BlockedLane]Lanes which are blocked by the incident.
var congestionCongestion?Info about the amount of congestion on the road around the incident.
var closedBool?Is the road completely closed?
var geometryIndexStartUInt64The index into the RouteStep geometry where the incident starts.
var geometryIndexEndUInt64?The index into the RouteStep geometry where the incident ends.
var subTypeString?Optional additional information about the type of incident (free-form text).
var subTypeDescriptionString?Optional descriptions about the type of incident (free-form text).
var iso31661Alpha2String?The ISO 3166-1 alpha-2 code of the country in which the incident occurs.
var iso31661Alpha3String?The ISO 3166-1 alpha-3 code of the country in which the incident occurs.
var affectedRoadNames[String]A list of road names affected by the incident.
var bboxBoundingBox?The bounding box over which the incident occurs.

Initialisers and methods

  • public init(id: String, incidentType: IncidentType, description: String?, longDescription: String?, creationTime: UtcDateTime?, startTime: UtcDateTime?, endTime: UtcDateTime?, impact: Impact?, lanesBlocked: [BlockedLane], congestion: Congestion?, closed: Bool?, geometryIndexStart: UInt64, geometryIndexEnd: UInt64?, subType: String?, subTypeDescription: String?, iso31661Alpha2: String?, iso31661Alpha3: String?, affectedRoadNames: [String], bbox: BoundingBox?)
LaneInfo

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct LaneInfo: Equatable, Hashable, Codable

The content of a visual instruction.

PropertyTypeDefaultDescription
var activeBool
var directions[String]
var activeDirectionString?

Initialisers and methods

  • public init(active: Bool, directions: [String], activeDirection: String?)
LocationSimulationState

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct LocationSimulationState: Equatable, Hashable, Codable

The current state of the simulation.

PropertyTypeDefaultDescription
var currentLocationUserLocation
var remainingLocations[GeographicCoordinate]
var biasLocationBias

Initialisers and methods

  • public init(currentLocation: UserLocation, remainingLocations: [GeographicCoordinate], bias: LocationBias)

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct NavigationCachingConfig: Equatable, Hashable, Codable
PropertyTypeDefaultDescription
var cacheIntervalSecondsInt64
var maxAgeSecondsInt64

Initialisers and methods

  • public init(cacheIntervalSeconds: Int64, maxAgeSeconds: Int64)

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct NavigationControllerConfig
PropertyTypeDefaultDescription
var waypointAdvanceWaypointAdvanceModeConfigures when navigation advances to the next waypoint in the route.
var stepAdvanceConditionStepAdvanceConditionConfigures when navigation advances to the next step in the route.
var arrivalStepAdvanceConditionStepAdvanceConditionA special advance condition used for the final 2 route steps (last and arrival). This exists because several of our step advance conditions require entry and exit from a step's geometry. The end of the route/arrival doesn't always accommodate the expected location updates for the core step advance condition.
var routeDeviationTrackingRouteDeviationTrackingConfigures when the user is deemed to be off course. NOTE: This is distinct from the action that is taken. It is only the determination that the user has deviated from the expected route.
var snappedLocationCourseFilteringCourseFilteringConfigures how the heading component of the snapped location is reported in TripState.

Initialisers and methods

  • public init(waypointAdvance: WaypointAdvanceMode, stepAdvanceCondition: StepAdvanceCondition, arrivalStepAdvanceCondition: StepAdvanceCondition, routeDeviationTracking: RouteDeviationTracking, snappedLocationCourseFiltering: CourseFiltering)

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct NavigationRecordingEvent: Equatable, Hashable, Codable

An event that occurs during navigation.

This is used for the optional session recording / telemetry.

PropertyTypeDefaultDescription
var timestampInt64The timestamp of the event in milliseconds since Jan 1, 1970 UTC.
var eventDataNavigationRecordingEventDataData associated with the event.

Initialisers and methods

  • public init(timestamp: Int64, eventData: NavigationRecordingEventData)

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct NavigationSessionSnapshot: Equatable, Hashable, Codable
PropertyTypeDefaultDescription
var savedAtUtcDateTime
var routeRoute
var tripStateTripState?

Initialisers and methods

  • public init(savedAt: UtcDateTime, route: Route, tripState: TripState?)

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct NavState

The navigation state.

This is typically created from an initial trip state and conditions for advancing navigation to the next step. Any internal navigation state is packed in here so that the navigation controller can remain functionally pure.

PropertyTypeDefaultDescription
var tripStateTripState
var stepAdvanceConditionStepAdvanceCondition

Initialisers and methods

  • public init(tripState: TripState, stepAdvanceCondition: StepAdvanceCondition)
OsrmWaypointProperties

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct OsrmWaypointProperties: Equatable, Hashable, Codable

Waypoint properties parsed from an OSRM-compatible server response.

NOTE: Some servers (such as Valhalla) may support additional parameters at request time which are not echoed back in the response time. This is unfortunate; PRs upstream would likely be welcomed! Similarly, if your server is OSRM-compatible and returns additional attributes, feel free to open a PR to include these as optional properties.

PropertyTypeDefaultDescription
var nameString?The name of the street that the waypoint snapped to.
var distanceDouble?The distance (in meters) between the snapped point and the input coordinate.

Initialisers and methods

  • public init(name: String?, distance: Double?)
Route

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Route: Equatable, Hashable, Codable

Information describing the series of steps needed to travel between two or more points.

NOTE: This type is unstable and is still under active development and should be considered unstable.

PropertyTypeDefaultDescription
var geometry[GeographicCoordinate]
var bboxBoundingBox
var distanceDoubleThe total route distance, in meters.
var waypoints[Waypoint]The ordered list of waypoints to visit, including the starting point. Note that this is distinct from the geometry which includes all points visited. A waypoint represents a start/end point for a route leg.
var steps[RouteStep]

Initialisers and methods

  • public init(geometry: [GeographicCoordinate], bbox: BoundingBox, distance: Double, waypoints: [Waypoint], steps: [RouteStep])
RouteStep

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct RouteStep: Equatable, Hashable, Codable

A maneuver (such as a turn or merge) followed by travel of a certain distance until reaching the next step.

PropertyTypeDefaultDescription
var geometry[GeographicCoordinate]The full route geometry for this step.
var distanceDoubleThe distance, in meters, to travel along the route after the maneuver to reach the next step.
var durationDoubleThe estimated duration, in seconds, that it will take to complete this step.
var roadNameString?The name of the road being traveled on (useful for certain UI styles).
var exits[String]A list of exits (name or number).
var instructionStringA description of the maneuver (ex: "Turn wright onto main street"). Note for UI implementers: the context this appears in (or doesn't) depends somewhat on your use case and routing engine. For example, this field is useful as a written instruction in Valhalla.
var visualInstructions[VisualInstruction]A list of instructions for visual display (usually as banners) at specific points along the step.
var spokenInstructions[SpokenInstruction]A list of prompts to announce (via speech synthesis) at specific points along the step.
var annotations[String]?A list of json encoded strings representing annotations between each coordinate along the step.
var incidents[Incident]A list of incidents that occur along the step.
var drivingSideDrivingSide?Which side of the road traffic drives on for this step. This is relevant for roundabouts: left-hand traffic (e.g. UK) uses clockwise roundabouts, while right-hand traffic uses counterclockwise roundabouts.
var roundaboutExitNumberUInt8?The exit number when entering a roundabout (1 = first exit, 2 = second, etc.).

Initialisers and methods

  • public init(geometry: [GeographicCoordinate], distance: Double, duration: Double, roadName: String?, exits: [String], instruction: String, visualInstructions: [VisualInstruction], spokenInstructions: [SpokenInstruction], annotations: [String]?, incidents: [Incident], drivingSide: DrivingSide?, roundaboutExitNumber: UInt8?)
SerializableNavState

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct SerializableNavState: Equatable, Hashable, Codable
PropertyTypeDefaultDescription
var tripStateTripState
var stepAdvanceConditionSerializableStepAdvanceCondition

Initialisers and methods

  • public init(tripState: TripState, stepAdvanceCondition: SerializableStepAdvanceCondition)
Speed

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Speed: Equatable, Hashable, Codable

The speed of the user from the location provider.

PropertyTypeDefaultDescription
var valueDoubleThe user's speed in meters per second.
var accuracyDouble?The accuracy of the speed value, measured in meters per second.

Initialisers and methods

  • public init(value: Double, accuracy: Double?)
SpokenInstruction

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct SpokenInstruction: Equatable, Hashable, Codable

An instruction that can be synthesized using a TTS engine to announce an upcoming maneuver.

Note that these do not have any locale information attached.

PropertyTypeDefaultDescription
var textStringPlain-text instruction which can be synthesized with a TTS engine.
var ssmlString?Speech Synthesis Markup Language, which should be preferred by clients capable of understanding it.
var triggerDistanceBeforeManeuverDoubleHow far (in meters) from the upcoming maneuver the instruction should start being spoken.
var utteranceIdUuidA unique identifier for this instruction. This is provided so that platform-layer integrations can easily disambiguate between distinct utterances, which may have the same textual content. UUIDs conveniently fill this purpose. NOTE: While it is possible to deterministically create UUIDs, we do not do so at this time. This should be theoretically possible though if someone cares to write up a proposal and a PR.

Initialisers and methods

  • public init(text: String, ssml: String?, triggerDistanceBeforeManeuver: Double, utteranceId: Uuid)
StepAdvanceResult

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct StepAdvanceResult

The step advance result is produced on every iteration of the navigation state machine and used by the navigation to build a new NavState instance for that update.

PropertyTypeDefaultDescription
var shouldAdvanceBoolThe step should be advanced.
var nextIterationStepAdvanceConditionThe next iteration of the step advance condition. This is what the navigation controller passes to the next instance of NavState on the completion of an update (e.g. a user location update). Use the helper methods on StepAdvanceResult to ensure proper state handling: - [StepAdvanceResult::next()] - Unified method that takes a boolean and handles state appropriately - [StepAdvanceResult::advance()] - Creates an advancing result with automatically reset state - [StepAdvanceResult::no_advance()] - Creates a non-advancing result preserving current state The trait method [StepAdvanceCondition::new_instance()] ensures that composite conditions (Or/And) properly reset all nested conditions when any condition triggers advancement. CRITICAL: When advancing, this must be a clean/reset state to prevent state leakage between steps.

Initialisers and methods

  • public init(shouldAdvance: Bool, nextIteration: StepAdvanceCondition)
TripProgress

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct TripProgress: Equatable, Hashable, Codable

High-level state describing progress through a route.

PropertyTypeDefaultDescription
var distanceToNextManeuverDoubleThe distance to the next maneuver, in meters.
var distanceRemainingDoubleThe total distance remaining in the trip, in meters. This is the sum of the distance remaining in the current step and the distance remaining in all subsequent steps.
var durationRemainingDoubleThe total duration remaining in the trip, in seconds.

Initialisers and methods

  • public init(distanceToNextManeuver: Double, distanceRemaining: Double, durationRemaining: Double)
TripSummary

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct TripSummary: Equatable, Hashable, Codable

Information pertaining to the user's full navigation trip. This includes simple stats like total duration and distance.

PropertyTypeDefaultDescription
var distanceTraveledDoubleThe total raw distance traveled in the trip, in meters.
var snappedDistanceTraveledDoubleThe total snapped distance traveled in the trip, in meters.
var startedAtUtcDateTimeWhen the trip was started.
var endedAtUtcDateTime?When the trip was completed or canceled.

Initialisers and methods

  • public init(distanceTraveled: Double, snappedDistanceTraveled: Double, startedAt: UtcDateTime, endedAt: UtcDateTime?)
UserLocation

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct UserLocation: Equatable, Hashable, Codable

The location of the user that is navigating.

In addition to coordinates, this includes estimated accuracy and course information, which can influence navigation logic and UI.

NOTE: Heading is absent on purpose. Heading updates are not related to a change in the user's location.

PropertyTypeDefaultDescription
var coordinatesGeographicCoordinate
var horizontalAccuracyDoubleThe estimated accuracy of the coordinate (in meters)
var courseOverGroundCourseOverGround?
var timestampDate
var speedSpeed?

Initialisers and methods

  • public init(coordinates: GeographicCoordinate, horizontalAccuracy: Double, courseOverGround: CourseOverGround?, timestamp: Date, speed: Speed?)
ValhallaLocationSearchFilter

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct ValhallaLocationSearchFilter: Equatable, Hashable, Codable

A set of optional filters to exclude candidate edges based on their attributes.

PropertyTypeDefaultDescription
var excludeTunnelBool?Whether to exclude roads marked as tunnels.
var excludeBridgeBool?Whether to exclude roads marked as bridges.
var excludeTollsBool?Whether to exclude roads with tolls.
var excludeFerryBool?Whether to exclude ferries.
var excludeRampBool?Whether to exclude roads marked as ramps.
var excludeClosuresBool?Whether to exclude roads marked as closed due to a live traffic closure.
var minRoadClassValhallaRoadClass?The lowest road class allowed.
var maxRoadClassValhallaRoadClass?The highest road class allowed.
var levelFloat?If specified, will only consider edges that are on or traverse the passed floor level. It will set search_cutoff to a default value of 300 meters if no cutoff value is passed. Additionally, if a search_cutoff is passed, it will be clamped to 1000 meters.

Initialisers and methods

  • public init(excludeTunnel: Bool? = nil, excludeBridge: Bool? = nil, excludeTolls: Bool? = nil, excludeFerry: Bool? = nil, excludeRamp: Bool? = nil, excludeClosures: Bool? = nil, minRoadClass: ValhallaRoadClass? = nil, maxRoadClass: ValhallaRoadClass? = nil, level: Float? = nil)
ValhallaWaypointProperties

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct ValhallaWaypointProperties: Equatable, Hashable, Codable

Waypoint properties supported by Valhalla servers.

Our docstrings are short here, since Valhalla is the final authority. Refer to https://valhalla.github.io/valhalla/api/turn-by-turn/api-reference/#locations for more details, including default values. Other Valhalla-based APIs such as Stadia Maps or Mapbox may have slightly different defaults. Refer to your vendor's documentation when in doubt.

NOTE: Waypoint properties will NOT currently be echoed back in OSRM format, so these are sent to the server one time.

PropertyTypeDefaultDescription
var headingUInt16?Preferred direction of travel for the start from the location. The heading is indicated in degrees from north in a clockwise direction, where north is 0°, east is 90°, south is 180°, and west is 270°. Avoid specifying this unless you really know what you're doing. Most use cases for this are better served by preferred_side.
var headingToleranceUInt16?How close in degrees a given street's angle must be in order for it to be considered as in the same direction of the heading parameter.
var minimumReachabilityUInt16?Minimum number of nodes (intersections) reachable for a given edge (road between intersections) to consider that edge as belonging to a connected region. Disconnected edges are ignored.
var radiusUInt16?The number of meters about this input location within which edges will be considered as candidates for said location. If there are no candidates within this distance, it will return the closest candidate within reason. This allows the routing engine to match another edge which is NOT the closest to your location, but in within this range. This can be useful if you have other constraints and want to disambiguate, but beware that this can lead to very strange results, particularly if you have specified other parameters like heading. This is an advanced feature and should only be used with extreme care.
var preferredSideValhallaWaypointPreferredSide?Determines whether the location should be visited from the same, opposite or either side of the road, with respect to the side of the road the given locale drives on. NOTE: If the location is not offset from the road centerline or is very close to an intersection, this option has no effect!
var displayCoordinateGeographicCoordinate?Latitude of the map location in degrees. If provided, the waypoint location will still be used for routing, but these coordinates will determine the side of the street.
var searchCutoffUInt32?The cutoff at which we will assume the input is too far away from civilization to be worth correlating to the nearest graph elements.
var nodeSnapToleranceUInt16?During edge correlation, this is the tolerance used to determine whether to snap to the intersection rather than along the street. If the snap location is within this distance from the intersection, the intersection is used instead.
var streetSideToleranceUInt16?A tolerance in meters from the edge centerline used for determining the side of the street that the location is on. If the distance to the centerline is less than this tolerance, no side will be inferred. Otherwise, the left or right side will be selected depending on the direction of travel.
var streetSideMaxDistanceUInt16?The max distance in meters that the input coordinates or display lat/lon can be from the edge centerline for them to be used for determining the side of the street. Beyond this distance, no street side is inferred.
var streetSideCutoffValhallaRoadClass?Disables the preferred_side when set to same or opposite if the edge has a road class less than that provided by street_side_cutoff.
var searchFilterValhallaLocationSearchFilter?A set of optional filters to exclude candidate edges based on their attributes.
var allowUturnsBool?`true`Determines whether U-Turns are allowed at the waypoint (if it is an intermediate waypoint, not the first or last). Defaults to true. This has the effect of converting a [WaypointKind::Break] into a Valhalla break_through, and a [WaypointKind::Via] into a through.
var nameString?Location or business name. The name may be used in the route narration directions, such as "You have arrived at <business name>." WARNING: this param is not echoed back in the response, so this can disappear when rerouting! NOTE: Serialized as waypoint_name in the waypoint properties blob so it cannot collide with the name of OsrmWaypointProperties (the snapped street name), which occupies the same blob on waypoints rebuilt from a route response (e.g. the remaining waypoints used for reroute requests). It is still sent to Valhalla as name.

Initialisers and methods

  • public init(heading: UInt16? = nil, headingTolerance: UInt16? = nil, minimumReachability: UInt16? = nil, radius: UInt16? = nil, preferredSide: ValhallaWaypointPreferredSide? = nil, displayCoordinate: GeographicCoordinate? = nil, searchCutoff: UInt32? = nil, nodeSnapTolerance: UInt16? = nil, streetSideTolerance: UInt16? = nil, streetSideMaxDistance: UInt16? = nil, streetSideCutoff: ValhallaRoadClass? = nil, searchFilter: ValhallaLocationSearchFilter? = nil, allowUturns: Bool? = nil, name: String? = nil)
VisualInstruction

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct VisualInstruction: Equatable, Hashable, Codable

An instruction for visual display (usually as banners) at a specific point along a RouteStep.

PropertyTypeDefaultDescription
var primaryContentVisualInstructionContentThe primary instruction content. This is usually given more visual weight.
var secondaryContentVisualInstructionContent?Optional secondary instruction content.
var subContentVisualInstructionContent?Optional sub-maneuver instruction content.
var triggerDistanceBeforeManeuverDoubleHow far (in meters) from the upcoming maneuver the instruction should start being displayed

Initialisers and methods

  • public init(primaryContent: VisualInstructionContent, secondaryContent: VisualInstructionContent?, subContent: VisualInstructionContent?, triggerDistanceBeforeManeuver: Double)
VisualInstructionContent

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct VisualInstructionContent: Equatable, Hashable, Codable

The content of a visual instruction.

PropertyTypeDefaultDescription
var textStringThe text to display.
var maneuverTypeManeuverType?A standardized maneuver type (if any).
var maneuverModifierManeuverModifier?A standardized maneuver modifier (if any).
var roundaboutExitDegreesUInt16?If applicable, the number of degrees you need to go around the roundabout before exiting. For example, entering and exiting the roundabout in the same direction of travel (as if you had gone straight, apart from the detour) would be an exit angle of 180 degrees.
var laneInfo[LaneInfo]?Detailed information about the lanes. This is typically only present in sub-maneuver instructions.
var exitNumbers[String]The exit number (or similar identifier like "8B").

Initialisers and methods

  • public init(text: String, maneuverType: ManeuverType?, maneuverModifier: ManeuverModifier?, roundaboutExitDegrees: UInt16?, laneInfo: [LaneInfo]?, exitNumbers: [String])
Waypoint

Struct · Sources/MapMapKit/Generated/ferrostar.swift

swift
public struct Waypoint: Equatable, Hashable, Codable

A waypoint along a route.

Within the context of Ferrostar, a route request consists of exactly one UserLocation and at least one Waypoint. The route starts from the user's location (which may contain other useful information like their current course for the [crate::routing_adapters::RouteRequestGenerator] to use) and proceeds through one or more waypoints.

Waypoints are used during route calculation, are tracked throughout the lifecycle of a trip, and are used for recalculating when the user deviates from the expected route.

Note that support for properties beyond basic geographic coordinates varies by routing engine.

PropertyTypeDefaultDescription
var coordinateGeographicCoordinate
var kindWaypointKind
var propertiesData?Optional additional properties that will be passed on to the [crate::routing_adapters::RouteRequestGenerator]. Most users should prefer convenience functions like [Waypoint::new_with_valhalla_properties] (or, on platforms like iOS and Android with UniFFI bindings, [crate::routing_adapters::valhalla::create_waypoint_with_valhalla_properties]). # Format guidelines This MAY be any format agreed upon by both the request generator and response parser. However, to promote interoperability, all implementations in the Ferrostar codebase MUST use JSON. We selected JSON is selected not because it is good, but because generics (i.e., becoming Waypoint<T>, where an example T is ValhallaProperties) would be way too painful, particularly for foreign code. Especially JavaScript. In any case, [crate::routing_adapters::RouteRequestGenerator] and [crate::routing_adapters::RouteResponseParser] implementations SHOULD document their level support for this, ideally with an exportable record type.

Initialisers and methods

  • public init(coordinate: GeographicCoordinate, kind: WaypointKind, properties: Data? = nil)

Enums (Ferrostar bindings (generated))

BlockedLane, CourseFiltering, DeviationCalculationPolicy, DeviationKind, DrivingSide, GraphHopperVoiceUnits, Impact, IncidentType, InstantiationError, LocationBias, ManeuverModifier, ManeuverType, ModelError, NavigationRecordingEventData, ParsingError, RecordingError, RouteDeviation, RouteDeviationTracking, RouteRequest, RoutingRequestGenerationError, SerializableStepAdvanceCondition, SimulationError, TripState, ValhallaRoadClass, ValhallaWaypointPreferredSide, WaypointAdvanceMode, WaypointKind, WellKnownRouteProvider

BlockedLane

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum BlockedLane: Equatable, Hashable, Codable

The lane type blocked by the incident.

CaseDescription
left
leftCenter
leftTurnLane
center
right
rightCenter
rightTurnLane
hov
CourseFiltering

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum CourseFiltering: Equatable, Hashable, Codable

Controls filtering/post-processing of user course by the NavigationController.

CaseDescription
snapToRouteSnap the user's course to the current step's linestring using the next index in the step's geometry.
rawUse the raw course as reported by the location provider with no processing.
DeviationCalculationPolicy

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum DeviationCalculationPolicy: Equatable, Hashable, Codable

Controls when a deviation-aware step-advance condition is allowed to evaluate, based on the user's current RouteDeviation status.

CaseDescription
alwaysAlways evaluate, regardless of deviation status.
whileOnRouteEvaluate while the user is still somewhere on the route polyline (current step or any future step), but suspend if the user is completely off the route.
whileOnCurrentStepEvaluate only while the user is within an acceptable deviation of the current step's polyline. Suspend on any deviation (whether off-step-but-on-route, or completely off-route).
DeviationKind

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum DeviationKind: Equatable, Hashable, Codable

The kind of deviation from the expected route.

CaseDescription
offStepOnRoute(deviationFromStepLine: Double)The user is off the current step, but still on the route polyline (on a future step). This can happen when the user takes a shortcut, GPS noise places them on a future step, or the route self-intersects. Step advance conditions can use this to limit advancement.
completelyOffRoute(deviationFromRouteLine: Double)The user is off the expected route entirely (not within threshold of any remaining step, neither the current one nor any future one).
DrivingSide

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum DrivingSide: Equatable, Hashable, Codable

Which side of the road traffic drives on.

This is needed by consumers like Android Auto to determine whether a roundabout should be rendered as clockwise (right-hand traffic) or counterclockwise (left-hand traffic).

CaseDescription
left
right
GraphHopperVoiceUnits

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum GraphHopperVoiceUnits: Equatable, Hashable, Codable
CaseDescription
metric
imperial
Impact

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum Impact: Equatable, Hashable, Codable

The impact of the incident that has occurred.

CaseDescription
unknown
critical
major
minor
low
IncidentType

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum IncidentType: Equatable, Hashable, Codable

The type of incident that has occurred.

CaseDescription
accident
congestion
construction
disabledVehicle
laneRestriction
massTransit
miscellaneous
otherNews
plannedEvent
roadClosure
roadHazard
weather
InstantiationError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum InstantiationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
OptionsJsonParseError
LocationBias

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum LocationBias: Equatable, Hashable, Codable

Controls how simulated locations deviate from the actual route line. This simulates real-world GPS behavior where readings often have systematic bias.

CaseDescription
left(Double)Simulates GPS bias by offsetting locations to the left of the route direction. The f64 parameter specifies the offset distance in meters.
right(Double)Simulates GPS bias by offsetting locations to the right of the route direction. The f64 parameter specifies the offset distance in meters.
random(Double)Simulates GPS bias by randomly choosing left or right offset on initialization and maintaining that bias throughout the route. The f64 parameter specifies the offset distance in meters. This mimics real-world GPS behavior where bias direction is random but typically remains consistent during a trip.
noneNo position bias - locations follow the route line exactly. This provides "perfect" GPS behavior, useful for testing basic route following without position uncertainty.
ManeuverModifier

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ManeuverModifier: Equatable, Hashable, Codable

Additional information to further specify a ManeuverType.

CaseDescription
uTurn
sharpRight
right
slightRight
straight
slightLeft
left
sharpLeft
ManeuverType

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ManeuverType: Equatable, Hashable, Codable

The broad class of maneuver to perform.

This is usually combined with ManeuverModifier in VisualInstructionContent.

CaseDescription
turn
newName
depart
arrive
merge
onRamp
offRamp
fork
endOfRoad
`continue`
roundabout
rotary
roundaboutTurn
notification
exitRoundabout
exitRotary
ModelError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ModelError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
PolylineGenerationError(error: String)

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum NavigationRecordingEventData: Equatable, Hashable, Codable

The event type.

For full replayability, we record things like rerouting, and not just location updates.

CaseDescription
stateUpdate(tripState: TripState, stepAdvanceCondition: SerializableStepAdvanceCondition)
routeUpdate(route: Route)
ParsingError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ParsingError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
InvalidRouteObject(error: String)
InvalidGeometry(error: String)
MalformedAnnotations(error: String)
InvalidStatusCode(code: String, description: String?)
UnknownParsingError
RecordingError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum RecordingError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError

A session recording error.

PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
SerializationError(error: String)Error during serialization.
RecordingNotEnabledRecording is not enabled for this controller.
DeserializationError(error: String)Error during deserialization.
RouteDeviation

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum RouteDeviation: Equatable, Hashable, Codable

Status information that describes whether the user is proceeding according to the route or not.

Note that the name is intentionally a bit generic to allow for expansion of other states. For example, we could conceivably add a "wrong way" status in the future.

CaseDescription
noDeviationThe user is proceeding on course within the expected tolerances; everything is normal.
deviation(kind: DeviationKind)The user has deviated from the expected route. Check the DeviationKind to determine if the user is still on the route polyline (off the current step but on a future step) or off the route entirely.
RouteDeviationTracking

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum RouteDeviationTracking

Determines if the user has deviated from the expected route.

CaseDescription
noneNo checks will be done, and we assume the user is always following the route.
staticThreshold(minimumHorizontalAccuracy: UInt16, maxAcceptableDeviation: Double)Detects deviation from the route using a configurable static distance threshold from the route line.
custom(detector: RouteDeviationDetector)An arbitrary user-defined implementation. You decide with your own RouteDeviationDetector implementation!
RouteRequest

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum RouteRequest: Equatable, Hashable, Codable

A route request generated by a RouteRequestGenerator.

CaseDescription
httpPost(url: String, headers: [String: String], body: Data)
httpGet(url: String, headers: [String: String])
RoutingRequestGenerationError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum RoutingRequestGenerationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
NotEnoughWaypoints
JsonError
UnknownRequestGenerationError
SerializableStepAdvanceCondition

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum SerializableStepAdvanceCondition: Equatable, Hashable, Codable
CaseDescription
manual
distanceToEndOfStep(distance: UInt16, minimumHorizontalAccuracy: UInt16)
distanceFromStep(distance: UInt16, minimumHorizontalAccuracy: UInt16, calculationPolicy: DeviationCalculationPolicy)
distanceEntryExit(distanceToEndOfStep: UInt16, distanceAfterEndStep: UInt16, minimumHorizontalAccuracy: UInt16, hasReachedEndOfCurrentStep: Bool)
distanceEntryAndSnappedExit(distanceToEndOfStep: UInt16, distanceAfterEndStep: UInt16, minimumHorizontalAccuracy: UInt16, hasReachedEndOfCurrentStep: Bool)
orAdvanceConditions(conditions: [SerializableStepAdvanceCondition])
andAdvanceConditions(conditions: [SerializableStepAdvanceCondition])
SimulationError

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum SimulationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
PropertyTypeDefaultDescription
var errorDescriptionString?
CaseDescription
PolylineError(error: String)Errors decoding the polyline string.
NotEnoughPointsNot enough points in the input.
TripState

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum TripState: Equatable, Hashable, Codable

The state of a navigation session.

This is produced by NavigationController methods including get_initial_state and update_user_location.

CaseDescription
idle(userLocation: UserLocation?)The navigation controller is idle and there is no active trip.
navigating(currentStepGeometryIndex: UInt64?, userLocation: UserLocation, snappedUserLocation: UserLocation, remainingSteps: [RouteStep], remainingWaypoints: [Waypoint], progress: TripProgress, summary: TripSummary, deviation: RouteDeviation, visualInstruction: VisualInstruction?, spokenInstruction: SpokenInstruction?, annotationJson: String?)The navigation controller is actively navigating a trip.
complete(userLocation: UserLocation, summary: TripSummary)The navigation controller has reached the end of the trip.
ValhallaRoadClass

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ValhallaRoadClass: Equatable, Hashable, Codable

A road class in the Valhalla taxonomy.

These are ordered from highest (fastest travel speed) to lowest.

CaseDescription
motorway
trunk
primary
secondary
tertiary
unclassified
residential
serviceOther
ValhallaWaypointPreferredSide

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum ValhallaWaypointPreferredSide: Equatable, Hashable, Codable

Specifies a preferred side for departing from / arriving at a location.

Examples:

  • Germany drives on the right side of the road. A value of same will only allow leaving or arriving at a location such that it is on your right.
  • Australia drives on the left side of the road. Passing a value of same will only allow leaving or arriving at a location such that it is on your left.
CaseDescription
sameYou must depart from or arrive at the location on the same side as you drive.
oppositeYou must depart from or arrive at the location on the opposite side as you drive.
eitherNo preference; you can depart or arrive from any direction.
WaypointAdvanceMode

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum WaypointAdvanceMode: Equatable, Hashable, Codable

Controls when a waypoint should be marked as complete.

While a route may consist of thousands of points, waypoints are special. A simple trip will have only one waypoint: the final destination. A more complex trip may have several intermediate stops. Just as the navigation state keeps track of which steps remain in the route, it also tracks which waypoints are still remaining.

Tracking waypoints enables Ferrostar to reroute users when they stray off the route line. The waypoint advance mode specifies how the framework decides that a waypoint has been visited (and is removed from the list).

NOTE: Advancing to the next step and advancing to the next waypoint are separate processes. This will not normally cause any issues, but keep in mind that manually advancing to the next step does not necessarily imply that the waypoint will be marked as complete!

CaseDescription
waypointWithinRange(Double)Advance when the waypoint is within a certain range of meters from the user's location. This condition is potentially more rigorous, requiring the user to actually visit within a range of every waypoint regardless of step advance.
waypointAlongAdvancingStep(Double)Advance when a waypoint is within a certain range of meters of any point on the advancing step. This condition considers the step being advanced, not the user's location. As a result, it can recover when your step advance conditions allow the user to skip forward on the route.
WaypointKind

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum WaypointKind: Equatable, Hashable, Codable

Describes characteristics of the waypoint for routing purposes.

CaseDescription
`break`Starts or ends a leg of the trip. Most routing engines will generate arrival and departure instructions. Some routing engines do not support multi-leg routes, so an intermediate break may behave like a [WaypointKind::Via].
viaA waypoint that is simply passed through, but will not have any arrival or departure instructions.
WellKnownRouteProvider

Enum · Sources/MapMapKit/Generated/ferrostar.swift

swift
public enum WellKnownRouteProvider: Equatable, Hashable, Codable

Configurations for built-in route providers.

CaseDescription
valhalla(endpointUrl: String, profile: String, optionsJson: String? = nil)A Valhalla-based routing API. Stadia Maps offers a commercially supported API. You can also substitute any URL to use a self-hosted server.
graphHopper(endpointUrl: String, profile: String, locale: String, voiceUnits: GraphHopperVoiceUnits, optionsJson: String? = nil)A GraphHopper-based routing API. GraphHopper offers a commercially supported API. You can also substitute any other URL to use a self-hosted server.

Protocols (Ferrostar bindings (generated))

AndAdvanceConditionsProtocol, DistanceEntryAndExitConditionProtocol, DistanceEntryAndSnappedExitConditionProtocol, DistanceFromStepConditionProtocol, DistanceToEndOfStepConditionProtocol, ManualStepConditionProtocol, NavigationCache, NavigationControllerProtocol, NavigationObserver, NavigationRecorderProtocol, NavigationReplayProtocol, NavigationSessionCacheProtocol, NavigationSessionProtocol, NavigatorProtocol, OrAdvanceConditionsProtocol, RouteAdapterProtocol, RouteDeviationDetector, RouteRequestGenerator, RouteResponseParser, StepAdvanceConditionProtocol

AndAdvanceConditionsProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol AndAdvanceConditionsProtocol: AnyObject, Sendable

Advance if all of the conditions are met (AND).

DistanceEntryAndExitConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol DistanceEntryAndExitConditionProtocol: AnyObject, Sendable

A stateful condition that requires the user to reach the end of the step then proceed past it to advance.

DistanceEntryAndSnappedExitConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol DistanceEntryAndSnappedExitConditionProtocol: AnyObject, Sendable

A stateful condition that requires the user to reach the end of the step then proceed past it to advance.

This variant uses route snapping (snapping to the combined current+next step geometry) for the exit check, making it more robust for pedestrian/hiking navigation where users may walk on the opposite side of the street or wander around the optimal path. The route-snapped exit check prevents premature advancement while still allowing natural pedestrian movement patterns. The exit distance is measured from the current step to the route-snapped position.

DistanceFromStepConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol DistanceFromStepConditionProtocol: AnyObject, Sendable

Advances once the user is at least [Self::distance] meters from the current step's polyline.

This results in delayed advance, but is more robust to spurious / unwanted step changes in scenarios including self-intersecting routes (sudden jumps to the next step) and pauses at intersections (advancing too soon before the maneuver is complete).

NOTE! This may be less robust to things like short steps, out-and-backs, and U-turns, where this may eagerly exit a current step before the user has traversed it if the start of the step is within range of the end.

DistanceToEndOfStepConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol DistanceToEndOfStepConditionProtocol: AnyObject, Sendable

Automatically advances when the user's location is close enough to the end of the step.

This results in an eager advance where the user will jump to the next step when the condition is met.

ManualStepConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol ManualStepConditionProtocol: AnyObject, Sendable

Never advances to the next step automatically; requires calling NavigationController::advance_to_next_step.

You can use this to implement custom behaviors in external code.

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationCache: AnyObject, Sendable

Initialisers and methods

  • func save(record: Data)
  • func load() -> Data?
  • func delete()

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationControllerProtocol: AnyObject, Sendable

Manages the navigation lifecycle through a route, returning an updated state given inputs like user location.

Notes for implementing a new platform:

  • A controller is bound to a single route; if you want recalculation, create a new instance.
  • This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state.

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationObserver: AnyObject, Sendable

Initialisers and methods

  • func onGetInitialState(state: NavState)
  • func onUserLocationUpdate(location: UserLocation, state: NavState)
  • func onAdvanceToNextStep(state: NavState)
  • func onRouteAvailable(route: Route)

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationRecorderProtocol: AnyObject, Sendable

Initialisers and methods

  • func getEvents() -> [NavigationRecordingEvent]
  • func getRecordingJson() throws -> String
  • func onAdvanceToNextStep(state: NavState)
  • func onGetInitialState(state: NavState)
  • func onRouteAvailable(route: Route)
  • func onUserLocationUpdate(location: UserLocation, state: NavState)

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationReplayProtocol: AnyObject, Sendable

A wrapper around NavigationRecording to facilitate replaying the event stream.

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationSessionCacheProtocol: AnyObject, Sendable

Initialisers and methods

  • func canResume() -> Bool: Check if the navigation session can be resumed.
  • func load() -> NavigationSessionSnapshot?: Load the navigation session record from the cache if it exists and is not stale.
  • func onAdvanceToNextStep(state: NavState)
  • func onGetInitialState(state: NavState)
  • func onRouteAvailable(route: Route)
  • func onUserLocationUpdate(location: UserLocation, state: NavState)

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigationSessionProtocol: AnyObject, Sendable

Initialisers and methods

  • func advanceToNextStep(state: NavState) -> NavState
  • func getInitialState(location: UserLocation) -> NavState
  • func route() -> Route
  • func updateUserLocation(location: UserLocation, state: NavState) -> NavState

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol NavigatorProtocol: AnyObject, Sendable

Core interface for navigation functionalities.

This trait defines the essential operations for a navigation state manager. This lets us build additional layers (e.g. event logging) around NavigationController in a composable manner.

Initialisers and methods

  • func route() -> Route
  • func getInitialState(location: UserLocation) -> NavState
  • func advanceToNextStep(state: NavState) -> NavState
  • func updateUserLocation(location: UserLocation, state: NavState) -> NavState
OrAdvanceConditionsProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol OrAdvanceConditionsProtocol: AnyObject, Sendable

Advance if any of the conditions are met (OR).

This is ideal for short circuit type advance conditions.

E.g. you may have:

  1. A short circuit detecting if the user has exceeded a large distance from the current step.
  2. A default advance behavior.
RouteAdapterProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol RouteAdapterProtocol: AnyObject, Sendable

The route adapter bridges between the common core and a routing backend where interaction takes place over a generic request/response flow (typically over a network; local/offline routers do not use this object as the interaction patterns are different).

This is essentially the composite of the RouteRequestGenerator and RouteResponseParser traits, but it provides one further level of abstraction which is helpful to consumers. As there is no way to signal compatibility between request generators and response parsers, the RouteAdapter provides convenience constructors which take the guesswork out of it, while still leaving consumers free to implement one or both halves.

In the future, we may provide additional methods or conveniences, and this indirection leaves the design open to such changes without necessarily breaking source compatibility. One such possible extension would be the ability to fetch more detailed attributes in real time. This is supported by the Valhalla stack, among others.

Ideas welcome re: how to signal compatibility between request generators and response parsers. I don't think we can do this in the type system, since one of the reasons for the split design is modularity, including the possibility of user-provided implementations, and these will not always be of a "known" type to the Rust side.

Initialisers and methods

  • func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest
  • func parseResponse(response: Data) throws -> [Route]
RouteDeviationDetector

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol RouteDeviationDetector: AnyObject, Sendable

A custom deviation detector (for extending the behavior of RouteDeviationTracking).

This allows for arbitrarily complex implementations when the provided ones are not enough. For example, detecting that the user is proceeding the wrong direction by keeping a ring buffer of recent locations, or perform local map matching.

Initialisers and methods

  • func checkRouteDeviation(route: Route, tripState: TripState) -> RouteDeviation: Determines whether the user is following the route correctly or not. NOTE: This function has a single responsibility. Side-effects like whether to recalculate a route are left to higher levels, and implementations should only be concerned with determining the facts. IMPORTANT: If you are short circuiting StepAdvanceCondition's to allow skipping steps, you must always fall back to checking the deviation from the full route line.
RouteRequestGenerator

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol RouteRequestGenerator: AnyObject, Sendable

A trait describing any object capable of generating RouteRequests.

The interface is intentionally generic. Every routing backend has its own set of parameters, including a "profile," max travel speed, units of speed and distance, and more. It is assumed that these properties will be set at construction time or otherwise configured before use, so that we can keep the public interface as generic as possible.

Implementations may be either in Rust (most popular engines should eventually have Rust glue code) or foreign code.

Initialisers and methods

  • func generateRequest(userLocation: UserLocation, waypoints: [Waypoint]) throws -> RouteRequest: Generates a routing backend request given the set of locations. While most implementations will treat the locations as an ordered sequence, this is not guaranteed (ex: an optimized router).
RouteResponseParser

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol RouteResponseParser: AnyObject, Sendable

A generic interface describing any object capable of parsing a response from a routing backend into one or more Routes.

Initialisers and methods

  • func parseResponse(response: Data) throws -> [Route]: Parses a raw response from the routing backend into a route. We use a sequence of octets as a common interchange format. as this works for all currently conceivable formats (JSON, PBF, etc.).
StepAdvanceConditionProtocol

Protocol · Sources/MapMapKit/Generated/ferrostar.swift

swift
public protocol StepAdvanceConditionProtocol: AnyObject, Sendable

When implementing custom step advance logic, this trait allows you to define whether the condition should advance to the next condition, the next step or not.

At the moment, these must be implemented in Rust.

Initialisers and methods

  • func shouldAdvanceStep(tripState: TripState) -> StepAdvanceResult: This callback method is used by a step advance condition to receive step updates. The step advance condition can choose based on its outcome and internal state whether to advance to the next step or not.
  • func newInstance() -> StepAdvanceCondition: Creates a clean instance of this condition with the same configuration but reset state. This is used by composite conditions (Or/And) to ensure proper state isolation when any condition triggers advancement. Implementation Requirements: - Stateless conditions: Return a copy/clone of self - Stateful conditions: Return a new instance with initial state but preserve configuration parameters - Composite conditions: Recursively create fresh instances of all nested conditions This method prevents the state leakage bugs that can cause rapid step advancement and jumping behavior in navigation.

Functions (Ferrostar bindings (generated))

advanceLocationSimulation, createFerrostarLogger, createNavigationSession, createNavigator, createOsrmResponseParser, createRouteFromOsrm, createRouteFromOsrmRoute, createValhallaRequestGenerator, createWaypointWithValhallaProperties, getRoutePolyline, locationSimulationFromCoordinates, locationSimulationFromPolyline, locationSimulationFromRoute, stepAdvanceAnd, stepAdvanceDistanceEntryAndExit, stepAdvanceDistanceEntryAndSnappedExit, stepAdvanceDistanceFromStep, stepAdvanceDistanceToEndOfStep, stepAdvanceManual, stepAdvanceOr

advanceLocationSimulation

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func advanceLocationSimulation(state: LocationSimulationState) -> LocationSimulationState

Returns the next simulation state based on the desired strategy. Results of this can be thought of like a stream from a generator function.

This function is intended to be called once/second. However, the caller may vary speed to purposefully replay at a faster rate (ex: calling 3x per second will be a triple speed simulation).

When there are now more locations to visit, returns the same state forever.

createFerrostarLogger

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createFerrostarLogger()
createNavigationSession

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createNavigationSession(route: Route, config: NavigationControllerConfig, observers: [NavigationObserver]) -> NavigationSession

Creates a new navigation session for the given route and configuration.

It returns an Arc-wrapped trait object implementing Navigator. If should_record is true, it creates a controller with event recording enabled.

createNavigator

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createNavigator(route: Route, config: NavigationControllerConfig, shouldRecord: Bool) -> Navigator

Creates a new navigation controller for the given route and configuration.

It returns an Arc-wrapped trait object implementing Navigator. If should_record is true, it creates a controller with event recording enabled.

createOsrmResponseParser

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createOsrmResponseParser(polylinePrecision: UInt32) -> RouteResponseParser

Creates a RouteResponseParser capable of parsing OSRM responses.

This response parser is designed to be fairly flexible, supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs which contain richer information like banners and voice instructions for navigation.

createRouteFromOsrm

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createRouteFromOsrm(routeData: Data, waypointData: Data, polylinePrecision: UInt32) throws -> Route

Creates a Route from OSRM data.

This uses the same logic as the OsrmResponseParser and is designed to be fairly flexible, supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs which contain richer information like banners and voice instructions for navigation.

createRouteFromOsrmRoute

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createRouteFromOsrmRoute(routeData: Data, waypoints: [Waypoint], polylinePrecision: UInt32) throws -> Route

Creates a Route from OSRM route data and ferrostar waypoints.

This uses the same logic as the OsrmResponseParser and is designed to be fairly flexible, supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs which contain richer information like banners and voice instructions for navigation.

createValhallaRequestGenerator

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createValhallaRequestGenerator(endpointUrl: String, profile: String, optionsJson: String?) throws -> RouteRequestGenerator

Creates a RouteRequestGenerator which generates requests to an arbitrary Valhalla server (using the OSRM response format).

This is provided as a convenience for use from foreign code when creating your own [routing_adapters::RouteAdapter].

createWaypointWithValhallaProperties

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func createWaypointWithValhallaProperties(coordinate: GeographicCoordinate, kind: WaypointKind, properties: ValhallaWaypointProperties) -> Waypoint

A convenience helper for creating waypoints with Valhalla rich location properties.

Regrettably this must live as a top-level function unless constructors for record types lands in UniFFI: https://github.com/mozilla/uniffi-rs/issues/1935.

getRoutePolyline

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func getRoutePolyline(route: Route, precision: UInt32) throws -> String

Helper function for getting the route as an encoded polyline.

Mostly used for debugging.

locationSimulationFromCoordinates

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func locationSimulationFromCoordinates(coordinates: [GeographicCoordinate], resampleDistance: Double?, bias: LocationBias) throws -> LocationSimulationState

Creates a location simulation from a set of coordinates.

Optionally resamples the input line so that there is a maximum distance between points.

locationSimulationFromPolyline

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func locationSimulationFromPolyline(polyline: String, precision: UInt32, resampleDistance: Double?, bias: LocationBias) throws -> LocationSimulationState

Creates a location simulation from a polyline.

Optionally resamples the input line so that there is no more than the specified maximum distance between points.

locationSimulationFromRoute

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func locationSimulationFromRoute(route: Route, resampleDistance: Double?, bias: LocationBias) throws -> LocationSimulationState

Creates a location simulation from a route.

Optionally resamples the route geometry so that there is no more than the specified maximum distance between points.

stepAdvanceAnd

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceAnd(conditions: [StepAdvanceCondition]) -> StepAdvanceCondition

Convenience function for creating an AndAdvanceConditions.

This composes multiple conditions together and advances to the next step if ALL of them trigger.

stepAdvanceDistanceEntryAndExit

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceDistanceEntryAndExit(distanceToEndOfStep: UInt16, distanceAfterEndOfStep: UInt16, minimumHorizontalAccuracy: UInt16) -> StepAdvanceCondition

Convenience function for creating a DistanceEntryAndExitCondition.

Requires the user to first travel within distance_to_end_of_step meters of the end of the step, and then travel at least distance_after_end_of_step meters away from the step geometry. This ensures the user completes the maneuver before advancing to the next step.

stepAdvanceDistanceEntryAndSnappedExit

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceDistanceEntryAndSnappedExit(distanceToEndOfStep: UInt16, distanceAfterEndOfStep: UInt16, minimumHorizontalAccuracy: UInt16) -> StepAdvanceCondition

Convenience function for creating a DistanceEntryAndSnappedExitCondition.

This variant uses route snapping for better handling of pedestrian/hiking navigation scenarios where users may walk on the opposite side of the street or wander around the optimal path. Requires the user to first travel within distance_to_end_of_step meters of the end of the step, and then the route-snapped position moves distance_after_end_of_step meters from the current step. The snapping to the combined route (current+next steps) prevents premature advancement.

The exit distance is automatically capped to the next step's length to prevent getting stuck on short steps.

Recommended values for pedestrian navigation: entry 20m, exit 2-5m.

stepAdvanceDistanceFromStep

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceDistanceFromStep(distance: UInt16, minimumHorizontalAccuracy: UInt16, calculationPolicy: DeviationCalculationPolicy) -> StepAdvanceCondition

Convenience function for creating a DistanceFromStepCondition.

This advances to the next step when the user is at least distance meters away from any point on the current route step geometry. Does not advance unless the reported location accuracy is minimum_horizontal_accuracy meters or better.

calculation_policy controls when this condition is permitted to evaluate based on the user's current route deviation status.

stepAdvanceDistanceToEndOfStep

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceDistanceToEndOfStep(distance: UInt16, minimumHorizontalAccuracy: UInt16) -> StepAdvanceCondition

Convenience function for creating a DistanceToEndOfStepCondition.

This advances to the next step when the user is within distance meters of the last point in the current route step. Does not advance unless the reported location accuracy is minimum_horizontal_accuracy meters or better.

stepAdvanceManual

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceManual() -> StepAdvanceCondition

Convenience function for creating a ManualStepCondition.

This never advances to the next step automatically. You must manually advance to the next step programmatically using a FerrostarCore platform wrapper or by calling [super::Navigator::advance_to_next_step] manually.

stepAdvanceOr

Function · Sources/MapMapKit/Generated/ferrostar.swift

swift
public func stepAdvanceOr(conditions: [StepAdvanceCondition]) -> StepAdvanceCondition

Convenience function for creating an OrAdvanceConditions.

This composes multiple conditions together and advances to the next step if ANY of them trigger.

Type aliases (Ferrostar bindings (generated))

UtcDateTime, Uuid

UtcDateTime

Type alias · Sources/MapMapKit/Generated/ferrostar.swift

swift
public typealias UtcDateTime = Date

Typealias from the type name used in the UDL file to the custom type. This is needed because the UDL type name is used in function/method signatures.

Uuid

Type alias · Sources/MapMapKit/Generated/ferrostar.swift

swift
public typealias Uuid = UUID

Typealias from the type name used in the UDL file to the custom type. This is needed because the UDL type name is used in function/method signatures.

MapMapValhalla

Classes (MapMapValhalla)

ValhallaMobileRouter

ValhallaMobileRouter

Class · Sources/MapMapValhalla/ValhallaMobileRouter.swift

swift
public final class ValhallaMobileRouter: OfflineRouter, @unchecked Sendable

OfflineRouter backed by the on-device Valhalla engine: valhalla-mobile's wrapper (https://github.com/Rallista/valhalla-mobile, MIT, SwiftPM product "Valhalla", iOS 16.4+) compiled against the Valhalla release and patch series the factory builds tiles with (tools/mobile-engine/engine.pin; mapMapValhallaEngineVersion in Package.swift). An engine older than the tiles answers 171 "No suitable edges" on every territory, which is why the version is pinned and guarded.

valhalla-mobile's Valhalla class takes a raw Valhalla request JSON and returns the raw response JSON. From 0.6 it throws Valhalla's errors instead of returning them; this router turns a thrown error back into the engine's {"code", "message"} envelope, which the Rust core parses and classifies exactly as Android's engine returns it.

This class lives in the separate MapMapValhalla product so apps opt in to the engine (which embeds a prebuilt valhalla-wrapper.xcframework), the SwiftPM equivalent of the Android SDK's compileOnly seam. Routing is CPU-bound native work, call it through MapMapKit/OfflineRouting/route(router:waypoints:costing:adr:), which hops off the caller's executor.

Initialisers and methods

  • public init(configPath: String) throws: Create a router from an absolute path of a valhalla.json whose mjolnir.tile_dir points at the territory's Valhalla tile layer.
  • public static func fromConfig(_ configFile: URL) throws -> ValhallaMobileRouter: Create a router from an existing valhalla.json config file.
  • public static func fromTileDir(_ tileDir: URL, scratchDir: URL) throws -> ValhallaMobileRouter: Create a router for a territory's Valhalla tile directory, writing a config file under scratchDir (e.g. the app's caches directory). swift let tiles = try await store.layerPath(territoryId: id, kind: .valhallaTiles) let router = try ValhallaMobileRouter.fromTileDir(tiles, scratchDir: cachesDir)
  • public func route(requestJson: String) -> String
  • public func close(): Release the native engine and the mapped tiles. Routing after this returns an error envelope.

Example

swift
import MapMapKit
import MapMapValhalla

// On-device routing over an installed territory's Valhalla tiles.
let store = TerritoryStore(rootDir: URL.applicationSupportDirectory, verifyingKeyHex: TerritoryKeys.hostedFactoryKeyHex)
let tiles = try await store.layerPath(territoryId: "uk", kind: .valhallaTiles)
let router = try ValhallaMobileRouter.fromTileDir(tiles, scratchDir: URL.cachesDirectory)
let route = try await OfflineRouting.route(
    router: router,
    waypoints: [RoutePoint(lat: 51.5072, lon: -0.1276), RoutePoint(lat: 51.4545, lon: -2.5879)],
    costing: .truck,
    adr: MapMap.defaultAdrProfile()
)
let engine = NavigationEngine(route: route)
print(try await engine.totalSteps())
router.close()

MapMapCarPlay

Classes (MapMapCarPlay)

CarPlayManager, ExampleCarPlaySceneDelegate

CarPlayManager

Class · Sources/MapMapCarPlay/CarPlayManager.swift

swift
public final class CarPlayManager: NSObject

Orchestrates one CarPlay connection end-to-end: the CPMapTemplate root and its delegate, the browse → preview → navigate activity states, and the active CPNavigationSession's lifecycle.

This is the class Mapbox's Navigation SDK ships (CarPlayManager/CarPlayManagerDelegate) and that Ferrostar's own docs point to as a gap in FerrostarCarPlayUI, Ferrostar leaves this wiring to each app's demo code (see DemoCarPlayModel.swift). MapMap ships it as SDK surface instead: host apps forward their CPTemplateApplicationSceneDelegate callbacks to sceneConnected(interfaceController:window:)/sceneDisconnected(interfaceController:) and implement CarPlayManagerDelegate for the parts that are necessarily app-specific (the map view, route selection, trip start).

Not a port of any Ferrostar source, this orchestration layer does not exist in FerrostarCarPlayUI. See ExampleCarPlaySceneDelegate.swift for the exact scene-delegate wiring.

PropertyTypeDefaultDescription
var isWaitingForConfigurationtrue from init until sceneConnected(interfaceController:window:) has run once. CarPlay scene callbacks are not guaranteed to arrive in the order you'd expect, iOS 18.5 has been observed delivering sceneWillEnterForeground on the CarPlay scene before didConnectInterfaceController:toWindow:, so anything that needs interfaceController/window/mapTemplate must check this (or simply rely on those properties being nil) rather than assume connection has completed just because some scene callback fired. This mirrors OsmAnd's CarPlay isWaitingForConfiguration pattern.
var interfaceControllerCPInterfaceController?
var carWindowCPWindow?
var mapTemplateCPMapTemplate?
var scaleAdjusterCarPlayWindowScaleAdjuster?
var activityCarPlayActivity.browsing
var navigationSessionCPNavigationSession?The active navigation session, when activity is .navigating. Held here (not duplicated by the delegate/host) so there is exactly one owner of the CarPlay-side trip lifecycle, per the platform note that duplicate references to the same session are a common source of "which copy is authoritative" bugs.
var sessionConfigurationCPSessionConfiguration?The CarPlay-suggested UI limits (keyboard/list availability) and content style (light/dark), kept live via CPSessionConfigurationDelegate. Consult sessionConfiguration.limitedUserInterfaces before presenting anything keyboard-driven (e.g. a CPSearchTemplate), CarPlay screens without a keyboard input (many aftermarket and built-in units) will otherwise dead-end the driver. This SDK does not ship a search template itself; if you add one, gate it on this.
var delegateCarPlayManagerDelegate?

Initialisers and methods

  • public override init()
  • public func sceneConnected(interfaceController: CPInterfaceController, window: CPWindow): Forward templateApplicationScene(_:didConnectInterfaceController:toWindow:) here. Creates the root CPMapTemplate, sets it as the scene's root template, and, only once window is actually attached to its scene, asks the delegate for a map view controller. Creating a MapLibre view before the window attaches is a known blank-map/crash bug class (the view has no real drawable size yet); this ordering is why the delegate callback happens here and not in init.
  • public func sceneDisconnected(): Forward templateApplicationScene(_:didDisconnectInterfaceController:fromWindow:) (or the window-less variant) here. Ends any active trip and releases everything scoped to the connection.
  • public func previewRoutes(for trip: CPTrip, textConfiguration: CPTripPreviewTextConfiguration? = nil): Show a route-choice preview for trip (CPMapTemplate.showRouteChoicesPreview). Call once route(s) have been computed for a chosen destination.
  • public func startTrip(_ trip: CPTrip, using routeChoice: CPRouteChoice) -> CPNavigationSession?: Start guidance for routeChoice. Ends any previous session first, there is only ever one active navigationSession.
  • public func updateNavigationState(_ state: NavigationState, units: CarPlayDistanceUnits = .localeDefault, locale: Locale = .current): Push the latest NavigationState from your NavigationEngine onto the active session. No-op if there is no active trip.
  • public func stopTrip(cancelled: Bool): End the active trip, if any. - Parameter cancelled: true for a driver/system cancellation (cancelTrip()); false for a normal finish, e.g. on arrival (finishTrip()).
  • public func refreshChrome(): Re-apply the current activity's chrome (buttons), call after something that affects them changes (e.g. a mute toggle), since CarPlayManagerDelegate is asked fresh each time.

Example

swift
import CarPlay
import MapMapCarPlay

final class SceneDelegate: NSObject, CPTemplateApplicationSceneDelegate {
    let carPlay = CarPlayManager()

    func templateApplicationScene(_ scene: CPTemplateApplicationScene,
                                  didConnect interfaceController: CPInterfaceController,
                                  to window: CPWindow) {
        carPlay.sceneConnected(interfaceController: interfaceController, window: window)
    }

    func templateApplicationScene(_ scene: CPTemplateApplicationScene,
                                  didDisconnect interfaceController: CPInterfaceController,
                                  from window: CPWindow) {
        carPlay.sceneDisconnected()
    }
}
// While navigating: carPlay.updateNavigationState(state) for every NavigationState.

ExampleCarPlaySceneDelegate

Class · Sources/MapMapCarPlay/ExampleCarPlaySceneDelegate.swift

swift
public final class ExampleCarPlaySceneDelegate: NSObject, CPTemplateApplicationSceneDelegate

Example CPTemplateApplicationSceneDelegate: forwards scene connect/ disconnect straight to a CarPlayManager. This is the entire contract, everything else (template stack, activity states, navigation session lifecycle) lives in the manager.

Initialisers and methods

  • public func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, didConnect interfaceController: CPInterfaceController, to window: CPWindow)
  • public func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, didDisconnect interfaceController: CPInterfaceController, from window: CPWindow)

Example

swift
// Info.plist, UIApplicationSceneManifest > UISceneConfigurations >
// CPTemplateApplicationSceneSessionRoleApplication:
//   UISceneDelegateClassName = MapMapCarPlay.ExampleCarPlaySceneDelegate
// It forwards connect and disconnect to a CarPlayManager, as in the CarPlayManager example.
import MapMapCarPlay

let delegate = ExampleCarPlaySceneDelegate()
print(delegate)

Structs (MapMapCarPlay)

CarPlayMeasurementLength, CarPlayWindowScaleAdjuster, RoadRef

CarPlayMeasurementLength

Struct · Sources/MapMapCarPlay/Models/CarPlayDistanceUnits.swift

swift
public struct CarPlayMeasurementLength: Sendable

A CarPlay-ready distance measurement: picks short vs. long units from a raw metre value, and rounds it to the step sizes CarPlay's estimate cards expect (never a distractingly precise number while driving).

PropertyTypeDefaultDescription
let measurementMeasurement<UnitLength>

Initialisers and methods

  • public init(units: CarPlayDistanceUnits, distanceM: Double, locale: Locale = .current)
  • public func rounded() -> Measurement<UnitLength>: Round to the step CarPlay's own trip-estimate cards use: 5 m/ft/yd under 50, 10 under 100, 50 under 500, 100 above; for kilometres or miles, whole numbers above 10, one decimal below.

CarPlayWindowScaleAdjuster

Struct · Sources/MapMapCarPlay/CarPlayWindowScaleAdjuster.swift

swift
public struct CarPlayWindowScaleAdjuster: Sendable

Mitigation for a known MapLibre Native iOS bug class: the renderer computes its display scale from UIScreen.main rather than the screen the map view is actually attached to (https://github.com/maplibre/maplibre-native/issues/3214). On CarPlay that produces the wrong pixel density, usually oversized or blurry labels/icons, because CPWindow.screen is very rarely the same UIScreen as the phone's.

This mirrors the approach Organic Maps' CarPlay integration uses (CarPlayWindowScaleAdjuster, compare the two screens' native scales and adjust the visual scale the map is told to render at): MapMap is headless, so it cannot reach into the host's MapLibre view directly, but this computes the correction factor and hands it to the host to apply to their own map view (e.g. as a style zoom-level offset, or by overriding the scale MapLibre reads if their integration exposes that hook).

Usage: create this after the CPWindow has attached (see CarPlayManager's connect flow, never before, the window has no screen until then), and again on contentStyleDidChange/on every reattach, since a CarPlay unit can be swapped or reconnected with a different physical display mid-session.

PropertyTypeDefaultDescription
let carScreenNativeScaleCGFloatThe native scale (points → pixels) of the screen the CarPlay window is actually presented on.
let phoneScreenNativeScaleCGFloatThe native scale of the phone's own main screen, what MapLibre Native (pre-fix) actually renders at regardless of which screen the view is attached to.
var correctionFactorCGFloatMultiply MapLibre's reported/assumed scale by this to get the scale the CarPlay screen actually needs. 1.0 when the two screens happen to share a native scale (nothing to correct) or when the phone's scale could not be determined.

Initialisers and methods

  • public init(carWindow: CPWindow, phoneScreen: UIScreen = .main): - Parameters: - carWindow: the CPWindow supplied by CPTemplateApplicationSceneDelegate.templateApplicationScene(_:didConnectInterfaceController:toWindow:). Must already be attached to its scene (has a non-default screen). - phoneScreen: the phone's own main screen. Defaults to UIScreen.main, the same value MapLibre Native reads internally, which is exactly what needs correcting for.
  • public func applyToContentScale(of view: UIView): Apply the correction to a view's contentScaleFactor directly. Suitable for plain UIView/CALayer-backed renderers; MapLibre's MLNMapView (or a MapLibre-Metal view) may need the factor applied through its own API instead if it manages scale itself, check your MapLibre version's CarPlay notes before relying on this shortcut.

RoadRef

Struct · Sources/MapMapCarPlay/Models/RoadRefs.swift

swift
public struct RoadRef: Equatable, Hashable, Sendable

One road-number badge to draw (SPEC 4.5): the text on the shield, its tier, the country whose signs it follows and the shield template. A mirror of the canonical RoadRef in web-sdk/src/road-signs.ts, plus source, the raw ref the text came from.

PropertyTypeDefaultDescription
let textStringText on the shield, the country's display prefix stripped where the sign does ("I 95" draws 95; GB, IE, FR, DE and NL keep the full text).
let tierStringTier id (gb-motorway, us-interstate, ...), "generic" for a ref with no national tier, "text" for a ref longer than six characters, which is never a badge.
let countryStringISO 3166-1 alpha-2 of the profile that resolved it, "" when unknown.
let a11yLabelStringSpoken label ("Motorway M25", "Interstate 95"); English only for now, like the canonical table.
let templateString?Shield template id; nil for a text-only ref.
let sourceStringThe raw ref as the engine reported it ("I 95"), the text a badge stands in for.

Initialisers and methods

  • public init(text: String, tier: String, country: String, a11yLabel: String, template: String?, source: String)

Enums (MapMapCarPlay)

BadgeSurface, CarPlayActivity, CarPlayAudioSession, CarPlayDistanceUnits, CarPlayMapButtons, CPLaneGuidanceConverter, ManeuverGlyph, MapMapCarPlay, RoadRefImage, RoadRefResolver

BadgeSurface

Enum · Sources/MapMapCarPlay/Models/RoadRefBadgeLayout.swift

swift
public enum BadgeSurface: Sendable

The surface a badge sits on: on dark it gets the white halo of SPEC 3.6.

CaseDescription
light
dark

CarPlayActivity

Enum · Sources/MapMapCarPlay/CarPlayManagerDelegate.swift

swift
public enum CarPlayActivity: Equatable, Sendable

Where CarPlayManager currently is in the browse → preview → navigate flow. Exposed so host apps can drive their own UI (e.g. a phone-side "navigating on CarPlay" banner) off the same state machine.

CaseDescription
browsingConnected, no destination chosen yet, the map template is showing free browse (pan/zoom) with the host's custom buttons, if any.
previewingRoutesOne or more RouteResults are being previewed (showRouteChoicesPreview) before the driver commits to one.
navigating(trip: CPTrip)A CPNavigationSession is active for the given trip.

CarPlayAudioSession

Enum · Sources/MapMapCarPlay/Audio/CarPlayAudioSession.swift

swift
public enum CarPlayAudioSession

AVAudioSession configuration for voice-prompt playback on CarPlay.

MapMapKit ships no TTS of its own, apps synthesise SpokenPrompt/text/SpokenPrompt/ssml themselves (typically with AVSpeechSynthesizer), same as on the phone. What CarPlay adds is a specific audio-session recipe so prompts duck the car's current audio source (music, phone calls) instead of fighting with it or going silent: category .playback, mode .voicePrompt, options [.duckOthers, .interruptSpokenAudioAndMixWithOthers], the combination settled on by mapbox-navigation-ios (#1864/#1933) after exactly this category/mode/options set produced the fewest "no audio on CarPlay" and "prompt cut off other audio entirely" reports.

Initialisers and methods

  • public static func configureForVoicePrompts() throws: Configure the shared AVAudioSession for CarPlay voice prompts. Call once when navigation starts (or when your CarPlay scene connects, if you want to be ready before the first prompt) and again if you've deactivated the session in between (e.g. after a phone call interruption). - Throws: whatever AVAudioSession.setCategory/setActive throw (e.g. another app holding an incompatible session category).
  • public static func deactivate() throws: Deactivate the session, e.g. when navigation ends. Notifies other apps so they can resume ducked audio.

CarPlayDistanceUnits

Enum · Sources/MapMapCarPlay/Models/CarPlayDistanceUnits.swift

swift
public enum CarPlayDistanceUnits: Sendable

Which distance units CarPlay should display: short/long unit pairs mirroring MKDistanceFormatter.Units, exposed independently so this module has no requirement on MKDistanceFormatter itself.

CaseDescription
localeDefaultFollow the given locale's measurement system (the default: feet → miles in the US, yards → miles in the UK, metres → kilometres elsewhere).
imperialFeet, then miles.
imperialWithYardsYards, then miles (UK road-signage convention).
metricMetres, then kilometres.

CarPlayMapButtons

Enum · Sources/MapMapCarPlay/CarPlayMapButtons.swift

swift
public enum CarPlayMapButtons

Ready-made CPMapButtons for the common navigation-app map controls. Entirely optional, CarPlayManagerDelegate lets host apps supply their own mapButtons array instead.

CPMapButton (like CPMapTemplate/CPNavigationSession) is main-actor-isolated by the CarPlay framework itself (CARPLAY_TEMPLATE_UI_ACTOR in CPTemplate.h), so this whole type is @MainActor.

Initialisers and methods

  • public static func zoomIn(action: @escaping () -> Void) -> CPMapButton
  • public static func zoomOut(action: @escaping () -> Void) -> CPMapButton
  • public static func recenter(action: @escaping () -> Void) -> CPMapButton
  • public static func toggleMute(isMuted: Bool, action: @escaping () -> Void) -> CPMapButton
  • public static func pan(action: @escaping () -> Void) -> CPMapButton

CPLaneGuidanceConverter

Enum · Sources/MapMapCarPlay/Models/CPLaneGuidance+MapMap.swift

swift
public enum CPLaneGuidanceConverter

Converts MapMap's OSRM-style LaneGuidance (direction strings, e.g. "left", "straight", "slight right") into CarPlay's angle-based CPLane/CPLaneGuidance (iOS 17.4+, and the non-deprecated CPLane initializer only from iOS 18.0).

This is a best-effort approximation, not a port: OSRM lane directions are discrete buckets, not measured angles, so each bucket is mapped to a representative angle (straight ahead = 0°, clockwise positive, mirroring CPTrafficSide.right's convention in CPManeuver.h). Host apps with more precise lane geometry (e.g. from their own map data) can bypass this and build CPLaneGuidance directly.

Initialisers and methods

  • public static func laneGuidance(for bannerLine: BannerLine) -> CPLaneGuidance?: Build a CPLaneGuidance from a sub BannerLine's lane diagram. Returns nil below iOS 18 (no non-deprecated CPLane initializer) or when there are no lanes to show.

ManeuverGlyph

Enum · Sources/MapMapCarPlay/Models/ManeuverGlyph.swift

swift
public enum ManeuverGlyph

Maps the OSRM-style maneuverType/maneuverModifier strings carried on BannerLine (see crates/sn-valhalla/src/translate.rs, map_maneuver_type: types depart, arrive, turn, new name, continue, on ramp, off ramp, fork, merge, roundabout, rotary, exit roundabout, exit rotary, notification; modifiers straight, slight left/left/sharp left, slight right/right/ sharp right, uturn), plus the manoeuvre's driving side (VisualBanner/drivingSide), onto MapMap's own direction icons for CPManeuver.symbolImage and onto CarPlay's CPManeuverType.

The icons are the approved MapMap set (map-assets/icons/directions/), shipped in this module's DirectionIcons.xcassets as vector PDF template images (generated by map-assets/icons/directions/generate-native.mjs). Every transform, including the left-hand-traffic mirror, is baked into the geometry, so CarPlay's image snapshot cannot lose a mirroring flag. Secondary road furniture carries 0.35 alpha, which a template image keeps: CarPlay tints the glyph for its light or dark card and the untravelled part of a roundabout stays the same colour, fainter.

PropertyTypeDefaultDescription
static let symbolPointSizeCGFloat50Point size the maneuver symbol is rendered at: the CarPlay Developer Guide's maximum for a first maneuver symbol (50 x 50 pt).

Initialisers and methods

  • public static func drivingSide(_ value: String?) -> String?: Normalises an engine-supplied driving side: "left" (UK-style left-hand traffic, roundabouts clockwise) or "right". Anything else, including nil, is unknown and returns nil: never a guess.
  • public static func iconName(maneuverType: String?, maneuverModifier: String?, drivingSide: String?) -> String: The MapMap direction icon name (turn_left, rotary_lht_slight_left, ...) for a manoeuvre. A mirror of the canonical iconNameForManeuver(type, modifier, drivingSide) in map-assets/icons/directions/generate.mjs; ManeuverGlyphTests checks it against a golden table generated from the canonical function, so the two cannot drift silently. There is no default driving side. A roundabout or rotary with a known side draws its ring in that circulation; with the side unknown it draws the plain turn glyph for its exit direction, and a u-turn the plain continue_uturn, never a guessed ring. Always returns a name with a bundled image.
  • public static func vectorImage(named name: String) -> UIImage?: The bundled vector icon name, unsized, as a template image.
  • public static func image(named name: String, pointSize: CGFloat = symbolPointSize) -> UIImage?: The icon name rendered from its vector data at pointSize (3x, so it is sharp on every CarPlay screen), as a template image: CarPlay supplies the colour, the alpha (including the 0.35 secondary) is the icon's own.
  • public static func symbolImage(maneuverType: String?, maneuverModifier: String?, drivingSide: String?) -> UIImage?: The symbol image for a manoeuvre (see iconName(maneuverType:maneuverModifier:drivingSide:)).
  • public static func cpManeuverType(maneuverType: String?, maneuverModifier: String?) -> CPManeuverType: The nearest CPManeuverType, for apps that also want the system's own presentation styling (CPManeuver.maneuverType, iOS 17.4+). Several MapMap/OSRM types have no exact CarPlay counterpart (merge, notification) and fall back to .followRoad.

MapMapCarPlay

Enum · Sources/MapMapCarPlay/MapMapCarPlay.swift

swift
public enum MapMapCarPlay

CarPlay turn-by-turn support for the MapMap iOS SDK.

MapMapCarPlay is a thin adapter layer: it converts NavigationEngine output (NavigationState/GuidanceUpdate, VisualBanner, SpokenPrompt, SpeedLimit) into CarPlay's own vocabulary (CPTrip, CPManeuver, CPTravelEstimates, CPNavigationSession), and provides CarPlayManager, an orchestrator that owns the CPMapTemplate root and the scene lifecycle so host apps don't have to reimplement it.

The SDK stays headless here too: MapMapCarPlay never creates a map renderer. The host app supplies its own MapLibre view (or any other UIViewController) through CarPlayManagerDelegate/carPlayManager(_:mapViewControllerFor:), and CarPlayManager only handles the CarPlay-specific scaffolding around it (window attachment timing, screen-scale correction, template stack, navigation-session lifecycle).

Layout

  • CarPlayManager, the CPTemplateApplicationSceneDelegate-facing orchestrator: browse → preview → navigate → stop activity states, the CPMapTemplate + its delegate, and the active CPNavigationSession.
  • CarPlayManagerDelegate, host hooks: supply the map view controller, customise map buttons, observe camera gestures.
  • CPTrip, CPManeuver, CPTravelEstimates converters (this module's Models/ directory), pure value conversions from MapMap's FFI types.
  • CarPlayWindowScaleAdjuster, mitigation for the CarPlay-screen scale bug class (MapLibre Native computes scale from UIScreen.main, not the CarPlay screen, maplibre-native#3214).
  • CarPlayAudioSession, the exact AVAudioSession configuration voice prompts need on CarPlay.
  • ExampleCarPlaySceneDelegate.swift, a compiled, heavily-commented integration example: Info.plist scene manifest keys, the com.apple.developer.carplay-maps entitlement, and the connect flow.

Attribution

Several converters in this module are ported from Ferrostar's FerrostarCarPlayUI (https://github.com/stadiamaps/ferrostar/tree/main/apple/Sources/FerrostarCarPlayUI, © Stadia Maps, Inc., BSD-3-Clause, the same licence already recorded for the pinned Ferrostar Rust crate in THIRD-PARTY-NOTICES.md), individual files carry a header noting what was ported. No Ferrostar Swift package is linked: everything here binds against MapMapKit's own generated types, per the "Ferrostar boundary" in ios/README.md, linking FerrostarCarPlayUI directly would pull in Ferrostar's own copy of the Rust core, duplicating sn_nav_core.

PropertyTypeDefaultDescription
static let requiredEntitlementThe CarPlay entitlement identifier apps must request from Apple (see "Requesting CarPlay Entitlements", https://developer.apple.com/documentation/carplay/requesting-carplay-entitlements) before this module's scenes can connect on a real head unit or in the CarPlay Simulator. Exposed as a constant so host apps can reference it (e.g. in onboarding copy) without retyping it.

RoadRefImage

Enum · Sources/MapMapCarPlay/Models/RoadRefImage.swift

swift
public enum RoadRefImage

MapMap road-number badges (SPEC 4.5 and 5.5) as UIImages, composed from the sign vectors in this module's Signs.xcassets (lane 3's native assets, copied by map-assets/signs/generate-car.mjs): the shield blank drawn in horizontal slices (its stretch regions widen to fit the text, everything else keeps its shape), the halo on dark surfaces, and the text as glyph vectors placed on the cap grid. No font is involved anywhere, and the images keep their true colours (never template rendering).

PropertyTypeDefaultDescription
static let carPlayMaxSizeCarPlay's limit for a text attachment in a manoeuvre instruction (CPManeuver.attributedInstructionVariants: "The maximum text attachment image size is 64x25 points").
static let carPlayHeightCGFloat23The badge height on CarPlay: 23 pt plus its 1 pt halo on each side fills the 25 pt attachment limit. SPEC 5.5 asks for 32; CarPlay cannot show more than 25.

Initialisers and methods

  • public static func image(for ref: RoadRef, height: CGFloat = 32, surface: BadgeSurface = .dark, scale: CGFloat = 3) -> UIImage?: The badge for ref at height points on surface, rendered at scale pixels per point; nil when nothing draws (a text-only ref, an unknown template or a character with no glyph).
  • public static func carPlayImage(for ref: RoadRef, scale: CGFloat = 3) -> UIImage?: The badge for a CarPlay manoeuvre instruction: within carPlayMaxSize (a long ref is drawn smaller rather than cropped), with a light variant (no halo) and a dark variant (white halo) registered for UIUserInterfaceStyle, both on the same canvas so the instruction does not shift when the panel changes appearance.
  • public static func attributedInstruction(_ text: String, refs: [RoadRef], badge: (RoadRef) -> UIImage? = { carPlayImage(for: $0) }) -> NSAttributedString?: text with a road-number badge for each of refs that has one, as CarPlay text attachments; nil when none of them draws. A badge replaces the ref where the text already names it as a whole word (the banner's primary text is often the ref itself, e.g. "A27"), so the instruction does not say it twice; otherwise the badge goes in front of the text. Refs with no badge (text-only, longer than six characters) are left as they are.

RoadRefResolver

Enum · Sources/MapMapCarPlay/Models/RoadRefs.swift

swift
public enum RoadRefResolver

Picks the road-number badges for a step's road (SPEC 4.5) from what the car SDK knows about it: the raw ref, its country, subdivision and road class.

A mirror of the canonical resolveRoadRef for those inputs. Natively there is no route relation network and no tile network, so a tier is chosen by its ref-prefix pattern only (the spec's third rule); RoadRefResolverTests checks this against a golden table computed by the canonical resolver itself, so the two cannot drift silently.

Never invents a ref: no ref, no badge. Refs over six characters come back as tier "text" with no template (shown as text, never a badge). At most three concurrent routes.

Initialisers and methods

  • public static func resolve(ref: String?, country: String?, subdivision: String?, roadClass: String?) -> [RoadRef]
  • public static func label(text: String, tier: String) -> String: "Motorway M25", "A road A259", "Interstate 95": the canonical roadRefLabel.

Protocols (MapMapCarPlay)

CarPlayManagerDelegate

CarPlayManagerDelegate

Protocol · Sources/MapMapCarPlay/CarPlayManagerDelegate.swift

swift
public protocol CarPlayManagerDelegate: AnyObject

Host app hooks for CarPlayManager.

MapMapKit is headless everywhere, including here: CarPlayManager owns the CarPlay chrome (template stack, navigation session lifecycle, screen-scale correction) but never renders a map itself. The one piece of UI it cannot supply on the host's behalf is the map view, that comes from carPlayManager(_:mapViewControllerFor:).

Initialisers and methods

  • func carPlayManager(_ manager: CarPlayManager, mapViewControllerFor window: CPWindow, scaleAdjuster: CarPlayWindowScaleAdjuster) -> UIViewController: Supply the view controller to place behind CarPlay's map template chrome, typically a thin wrapper around your own MLNMapView (MapLibre) instance, styled with styleForNavigation(styleJson:). Called exactly once per connection, after window has already been attached to its CPTemplateApplicationScene (window.screen and window.mapButtonSafeAreaLayoutGuide are valid), this is the point at which it is safe to create a MapLibre view. Creating one any earlier is a known crash/blank-map bug class in MapLibre Native iOS tied to the window not yet reporting a real drawable size. Use scaleAdjuster to correct for CarPlay's screen-scale mismatch (maplibre-native#3214) before or as you configure your map view's layer.
  • func carPlayManager(_ manager: CarPlayManager, mapButtonsFor activity: CarPlayActivity) -> [CPMapButton]?: Customise the map template's mapButtons for the current CarPlayActivity. Return nil to keep whatever CarPlayManager last set (its default is empty, most apps will want to provide at least a mute toggle via CarPlayMapButtons).
  • func carPlayManager(_ manager: CarPlayManager, leadingNavigationBarButtonsFor activity: CarPlayActivity) -> [CPBarButton]?: The trailing/leading navigation-bar buttons (e.g. "Cancel", "Go") for the current activity. Return nil to keep CarPlay's defaults (none).
  • func carPlayManager(_ manager: CarPlayManager, trailingNavigationBarButtonsFor activity: CarPlayActivity) -> [CPBarButton]?
  • func carPlayManager(_ manager: CarPlayManager, didSelectRouteChoice routeChoice: CPRouteChoice, for trip: CPTrip): The driver picked a route to preview/select. Most apps will store routeChoice.mapMapRouteResult and, once the driver taps "Go" (carPlayManager(_:didStartTrip:using:)), build a NavigationEngine from it.
  • func carPlayManager(_ manager: CarPlayManager, didStartTrip trip: CPTrip, using routeChoice: CPRouteChoice): The driver committed to navigating routeChoice. Start your NavigationEngine here and feed its states back through CarPlayManager/updateNavigationState(_:) on every tick.
  • func carPlayManager(_ manager: CarPlayManager, didEndTrip trip: CPTrip, cancelled: Bool): The trip ended, either the driver/system cancelled it (cancelled == true, e.g. mapTemplateDidCancelNavigation) or your own code called CarPlayManager/stopTrip(cancelled:) (e.g. on arrival). Stop your NavigationEngine here.
  • func carPlayManager(_ manager: CarPlayManager, didUpdateZoomWithScale scale: CGFloat, velocity: CGFloat)
  • func carPlayManager(_ manager: CarPlayManager, didUpdateRotationWithRadians radians: CGFloat, velocity: CGFloat)
  • func carPlayManager(_ manager: CarPlayManager, didUpdatePitchAtCenter center: CGPoint)