Documentation menu
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 inwebsite/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.
// 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: 219 declarations
- MapMapValhalla: 1 declarations
- MapMapCarPlay: 16 declarations
MapMapKit
Classes (MapMapKit)
CoreLocationProvider, HTTPChannelFetcher, URLSessionProbeUploader, VoiceGuidance
CoreLocationProvider
Class · Sources/MapMapKit/Navigation/CoreLocationProvider.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.
| Property | Type | Default | Description |
|---|---|---|---|
var locations | AsyncThrowingStream<LocationSample, Error> |
Initialisers and methods
public init(configuration: Configuration = Configuration())
Nested: CoreLocationProvider.Configuration.
Example
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
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).
| Property | Type | Default | Description |
|---|---|---|---|
let source | ChannelSource | ||
var bytesReceived | Int64 | Total bytes received so far. | |
var lastFailedStatus | Int? | 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
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
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
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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var isSpeaking | Bool | Whether 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 muted | Bool | false | Whether announcements are muted. Toggle freely mid-drive; muting also stops anything mid-utterance. |
var volume | Float | 1.0 | Announcement 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.nilkeeps the device default voice. - baseRate: baseAVSpeechUtterancerate (platform default when omitted).public func handle(_ update: GuidanceUpdate): Consume one guidance update. Cheap; call it for every emission ofNavigationEngine/navigate(provider:).public func handle(_ state: NavigationState): Convenience overload forNavigationEngine/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
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
NavigationEngine
Actor · Sources/MapMapKit/Navigation/NavigationEngine.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 byOfflineRouting/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:NavCoreErrorif 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 fromproviderinto 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 withNavCoreErrorif 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
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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var territories | [TerritoryInfo] | [] | The installed territories as of the last refresh or mutation. |
var acceptsCustomRegions | Bool | Whether 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, ornilto 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.snpkgarchive. 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 pollscancelbetween archive entries, before verification and before promotion; a tripped token (or a cancelled calling task) yields.cancelledwith 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; seeinstall(snpkg:cancel:).public func installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: [MapLayerKind] = [], cancel: CancelToken = CancelToken()) async throws -> ChannelInstallOutcome: InstallterritoryIdfrom its channel: the first-install counterpart ofapplyUpdate(territoryId:manifestJson:manifestSigBase64:fetcher:).indexJson/indexSigBase64are the exact served bytes of the channel index and its detached signature; the channel's latest version is installed, fetching only the layers not inomit. 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 trippedcancel(or a cancelled calling task) yields.cancelledwith nothing installed. - Throws:NavCoreError/Verification(message:)if a signature or hash does not verify, including aregion-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: BringterritoryIdto 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 throughcheckForUpdate(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 fromsourceand every layer relative to it with anHTTPChannelFetcher.cancelalso 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 theterritory_id,index_urlandindex_sig_urlof aPOST /v1/jobs/territoryresult. 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/noRegionKeyif this store has no region key;ChannelSourceErrorfor 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: MarkterritoryIdactive; 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/valhallaTilesfor the on-device router,MapLayerKind/pmtilesfor 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'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<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.indexJsonmust be the exact bytes served asindex.jsonandindexSigBase64the content ofindex.json.sig; the remote manifest is fetched and verified throughfetcher(the app's download transport, URLSession, an air-gapped mirror, …, the core decides what to fetch and cryptographically verifies everything itself). Returnsnilwhen 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 throughfetcher, 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 bycheckForUpdate(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 pollscancelbefore 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 interruptfetcherwhile it is inside a transfer: give the fetcher the same token and have it pollisCancelled()between chunks (or cancel itsURLSessionTask). Whatever the fetcher then throws, a tripped token reports.cancelledrather 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; seeapplyUpdate(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
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
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.
| Property | Type | Default | Description |
|---|---|---|---|
let indexURL | URL | ||
let indexSigURL | URL | ||
let layerBaseURL | URL | Layer paths are appended to this. | |
static let defaultGateway | The 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) andGET /territories/index.sig.public static func customRegion(territoryId: String, indexURL: URL, indexSigURL: URL) throws -> ChannelSource: A custom region's own one-territory channel, from theindex_url/index_sig_urlof aPOST /v1/jobs/territoryresult. The gateway serves the index at<base>/v1/territories/<id>/index.jsonand the layers under<base>/territories/<id>/..., so the layer base is<base>. Any other.../index.json(a mirror of the region directory, laid out asSN_REGION_DIR/<id>/) resolves layers next to the index. - Throws:ChannelSourceErrorifterritoryIdis not a custom-region id orindexURLdoes not end inindex.json.public static func isCustomRegionId(_ territoryId: String) -> Bool: WhetherterritoryIdhas the shape the gateway gives custom regions:region-plus 16 lowercase hex characters.
CoreLocationProvider.Configuration
Struct · Sources/MapMapKit/Navigation/CoreLocationProvider.swift
public struct Configuration: Sendable
Configuration forwarded to CLLocationManager.
| Property | Type | Default | Description |
|---|---|---|---|
var desiredAccuracy | CLLocationAccuracy | Desired accuracy; vehicular guidance wants kCLLocationAccuracyBestForNavigation. | |
var distanceFilter | CLLocationDistance | Distance filter in metres (kCLDistanceFilterNone = every fix). | |
var activityType | CLActivityType | Activity type hint for the platform's fusion. | |
var allowsBackgroundLocationUpdates | Bool | Whether 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
public struct CorpusFormatError: Error, Equatable, LocalizedError
A .drive.jsonl document violated the corpus format.
| Property | Type | Default | Description |
|---|---|---|---|
let message | String | ||
var errorDescription | String? |
Initialisers and methods
public init(_ message: String)
DriveCorpus
Struct · Sources/MapMapKit/Replay/DriveCorpus.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.
| Property | Type | Default | Description |
|---|---|---|---|
static let formatVersion | The corpus format version this parser accepts. | ||
let header | DriveHeader | ||
let fixes | [DriveFix] |
Initialisers and methods
public static func parse(_ jsonl: String) throws -> DriveCorpus: Parse and validate a corpus from JSON-lines text. - Throws:CorpusFormatErrordescribing 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
public struct DriveFix: Equatable, Sendable
One GPS fix line of a corpus. tMs is milliseconds since drive start.
| Property | Type | Default | Description |
|---|---|---|---|
let tMs | Int64 | ||
let lat | Double | ||
let lon | Double | ||
let speedMps | Double? | ||
let bearingDeg | Double? | ||
let horizontalAccuracyM | Double? |
DriveHeader
Struct · Sources/MapMapKit/Replay/DriveCorpus.swift
public struct DriveHeader: Equatable, Sendable
Header line of a .drive.jsonl corpus.
| Property | Type | Default | Description |
|---|---|---|---|
let formatVersion | Int | ||
let name | String | ||
let description | String | ||
let routeFixture | String | ||
let seed | Int64 |
LocationSample
Struct · Sources/MapMapKit/Navigation/LocationProvider.swift
public struct LocationSample: Equatable, Sendable
One position sample fed into guidance.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | Latitude in decimal degrees (WGS84). | |
var lon | Double | Longitude in decimal degrees (WGS84). | |
var timestampMs | Int64 | Milliseconds since the Unix epoch. | |
var speedMps | Double? | Speed over ground in metres per second, when the source reports it. | |
var bearingDeg | Double? | Course over ground, degrees clockwise from true north, [0, 360). | |
var horizontalAccuracyM | Double? | 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)
NavigationCameraInterpolator
Struct · Sources/MapMapKit/Navigation/NavigationCameraInterpolator.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:
- 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. - 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.
| Property | Type | Default | Description |
|---|---|---|---|
static let bearingSmoothAlpha | Double | 0.35 | Per-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 standstillSpeedMps | Double | 0.5 | Below 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 extrapolationCap | Double | 1.5 | Ceiling 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 minFixInterval | TimeInterval | 0.10 | The 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 maxFixInterval | TimeInterval | 1.4 | |
static let nominalFixInterval | TimeInterval | 1.0 | Assumed 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 intervalWindow | Int | 3 | How 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 onRouteToleranceM | Double | 25 | How 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 tangentWindowM | Double | 15 | Half-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 hasFix | Bool | True once at least one fix has been fed. | |
var latestBearingDeg | Double? | 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 fixInterval | TimeInterval | The 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 pacingInterval | TimeInterval | The 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 isFollowingRoute | Bool | True 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.tsdocuments 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'salongMis an arc length measured against whatever polyline was current when the fix arrived, andstate(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 honoursonRouteToleranceMexactly asfeed(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. BelowstandstillSpeedMpsthe 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 attimestamp.nilbefore 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 asextrapolationCap, 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 thanonRouteToleranceMoff 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 differencefrom -> to, in[-180, 180). Positive is clockwise. The half-open range matchesshortestArcDeltaDegon the Android side down to the boundary: an exact 180 degree reversal resolves anticlockwise on both platforms rather than one each way.
NavigationState
Struct · Sources/MapMapKit/Navigation/NavigationState.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.
| Property | Type | Default | Description |
|---|---|---|---|
let fix | LocationSample | ||
let update | GuidanceUpdate | ||
var isArrived | Bool | True once the core reports arrival at the destination. | |
var needsReroute | Bool | True 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var locations | AsyncThrowingStream<LocationSample, Error> |
Initialisers and methods
public init(corpus: DriveCorpus, timeScale: Double = 1.0, epochStartMs: Int64 = 0): - Parameters: - corpus: a parsed corpus (seeDriveCorpus/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
public struct SignedChannelIndex: Equatable, Sendable
The exact served bytes of a channel index and its detached signature.
| Property | Type | Default | Description |
|---|---|---|---|
let json | String | ||
let signatureBase64 | String |
SpeechSessionRefCount
Struct · Sources/MapMapKit/Navigation/VoiceGuidance.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.
| Property | Type | Default | Description |
|---|---|---|---|
var outstanding | Int | 0 | Utterances 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. Returnstruewhen that was the last one, nothing is speaking or queued, so the audio session should be deactivated. Spurious callbacks after areset()never trigger another deactivation.public mutating func reset() -> Bool: Clear everything (stop()). Returnstruewhen there was anything outstanding, i.e. the session should be deactivated.
VoiceProsody
Struct · Sources/MapMapKit/Navigation/VoiceGuidance.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).
| Property | Type | Default | Description |
|---|---|---|---|
let rate | Float | `AVSpeechUtterance` rate (0–1 scale; the platform default is `AVSpeechUtteranceDefaultSpeechRate`) | AVSpeechUtterance rate (0–1 scale; the platform default is AVSpeechUtteranceDefaultSpeechRate). |
let pitchMultiplier | Float | Utterance pitch multiplier (1.0 = neutral). | |
let interrupt | Bool | Whether pending speech is stopped before this prompt. |
Initialisers and methods
public static func prosody(for severity: InstructionSeverity, baseRate: Float = AVSpeechUtteranceDefaultSpeechRate) -> VoiceProsody: Prosody forseverityatbaseRate(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 forseverity, ornilwhen the severity plays none by default (info stays silent so a chime does not precede every routine manoeuvre). Assets are generated byscripts/generate-earcons.py.public static func earconURL(for severity: InstructionSeverity) -> URL?: URL of the earcon WAV inside MapMapKit's resource bundle, ornilfor severities that play none.
Enums (MapMapKit)
AdrCompliance, ChannelSourceError, ChannelSync, GuidanceDisplay, MapMap, MapMapKitError, OfflineRouting, ProbeUploadOutcome, TerritoryKeys, ValhallaConfigWriter
AdrCompliance
Enum · Sources/MapMapKit/Adr/AdrCompliance.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):
- Pre-route, pass the
AdrProfiletoOfflineRouting/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. - 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, andforbiddenCategories(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 byprofilepass through a tunnel ofcategory? 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
public enum ChannelSourceError: Error, Equatable, CustomStringConvertible
Why a ChannelSource could not be built.
| Property | Type | Default | Description |
|---|---|---|---|
var description | String |
| Case | Description |
|---|---|
notACustomRegion(String) | |
notAnIndexURL(String) | |
noRegionKey | The store was built without a region key, so it refuses every custom region. |
ChannelSync
Enum · Sources/MapMapKit/Territory/TerritoryStore.swift
public enum ChannelSync: Sendable
What TerritoryStore/sync(territoryId:indexJson:indexSigBase64:fetcher:omit:cancel:) did.
| Case | Description |
|---|---|
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. |
cancelled | The CancelToken was tripped; nothing changed on disk. |
GuidanceDisplay
Enum · Sources/MapMapKit/Navigation/NavigationState.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; renderprimary.textwith the arrow named byprimary.maneuverType/maneuverModifier).public static func spokenPrompt(_ update: GuidanceUpdate) -> SpokenPrompt?: The spoken prompt currently due. Handssml ?? texttoAVSpeechSynthesizer, and de-duplicate byutteranceId, 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'sInstructionSeverityfor 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 amaxspeedannotation 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.nilwith stock map data (no annotation);.unlimited/.unknowndistinguish 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
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 anyLocationProvider(CoreLocationProviderlive,ReplayLocationProviderfor 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: AGuidanceConfigwith the core's documented defaults.public static func defaultAdrProfile() -> AdrProfile: AnAdrProfilewith the core's documented defaults: EU maximum authorised dimensions (Council Directive 96/53/EC), no dangerous goods.
MapMapKitError
Enum · Sources/MapMapKit/MapMapKit.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).
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
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
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-attributedMapMapKitError/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 aValhallaMobileRouter. - waypoints: at least twoRoutePoints, in visit order. - costing: the Valhalla costing model; must beCostingModel/truckwhenadris 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 aRouteResult.
ProbeUploadOutcome
Enum · Sources/MapMapKit/Navigation/ProbeContribution.swift
public enum ProbeUploadOutcome: Sendable, Equatable
The outcome of one upload attempt, surfaced through
URLSessionProbeUploader's result callback for observability and tests.
| Case | Description |
|---|---|
accepted | 202, accepted and stored. |
refused | 403, the key is not opted in; dropped, not retried. |
notEnabled | 501, server collection is not enabled (SN_PROBE_DIR unset); dropped. |
rejected | 400/other 4xx, malformed or unacceptable; dropped, not retried. |
gaveUp | Transport error or 5xx after exhausting retries; given up on. |
TerritoryKeys
Enum · Sources/MapMapKit/Territory/TerritoryKeys.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.
| Property | Type | Default | Description |
|---|---|---|---|
static let hostedFactoryKeyHex | The factory key: verifies every country package on the hosted channel (https://api.mapmap.ai/territories). Also published at mapmap.ai/docs/territories. | ||
static let hostedRegionKeyHex | The 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
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).
| Property | Type | Default | Description |
|---|---|---|---|
static let defaultMaxCacheBytes | Int64 | 268_435_456 | Mobile 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'sMapLayerKind/valhallaTileslayer).
Protocols (MapMapKit)
LocationProvider, OfflineRouter, ProbeUploader
LocationProvider
Protocol · Sources/MapMapKit/Navigation/LocationProvider.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.
| Property | Type | Default | Description |
|---|---|---|---|
var locations | AsyncThrowingStream<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
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
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 fromProbeCollector.finishJson, off to be POSTed to/v1/probe. Fire-and-forget.
Functions (MapMapKit)
contributingProbe
Function · Sources/MapMapKit/Navigation/ProbeContribution.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
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
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 byroute_offlineinvalhalla_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_mdefaults to0.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
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-relativerel_path(e.g.territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local filedest_path.expected_blake3is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouterImpl
Class · Sources/MapMapKit/Generated/mapmap.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
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.arriveddistinguishes 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 toPOST /v1/probe, orNonewhen 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_mpsis the device's reported ground speed when available (preferred); passNoneto 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
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 atroot_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 byPOST /v1/jobs/territory) signed byregion_key_hex, the public half of the gateway's region signing key. The keys are partitioned by id: the region key verifiesregion-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 throughfetcher, 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 aCancelToken. 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. Givefetcherthe 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 reportsCancelledrather 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_jsonmust be the exact bytes served asindex.jsonandindex_sig_base64the content ofindex.json.sig; the remote manifest is fetched and verified throughfetcher. ReturnsNonewhen 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 aCancelToken. 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:omitnames the kinds to leave out (e.g.PmtilesandExtra("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 inomitis never requested, so it is never metered and never stored.index_json/index_sig_base64are the exact served bytes ofindex.jsonandindex.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.snpkgarchive (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 aCancelToken. 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.snpkgarchive. 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 returnedTerritorySearchholds 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 tonew_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'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<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. Theglyphsendpoint 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
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).nearbiases ranking towards the given point and fills each result'sdistance_m;limitcaps 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var heightM | Double | Vehicle height in metres. | |
var widthM | Double | Vehicle width in metres. | |
var lengthM | Double | Vehicle length in metres. | |
var grossWeightT | Double | Gross combination weight in metric tonnes. | |
var axleLoadT | Double? | Heaviest single-axle load in tonnes, if known. | |
var axleCount | UInt32? | Number of axles, if known. | |
var hazmat | Bool | Whether the vehicle carries dangerous goods at all. | |
var tunnelCode | AdrTunnelCode? | 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
public struct AvailableUpdate: Equatable, Hashable
An update the channel offers for an installed territory.
| Property | Type | Default | Description |
|---|---|---|---|
var version | String | The channel's latest version for the territory. | |
var changedLayers | [ChangedLayer] | Layers that must be downloaded. | |
var installedBytes | UInt64 | Uncompressed total of the changed layers, on-device disk, not metered wire bytes. Same warning as [UpdatePlan::installed_bytes]. | |
var manifestJson | String | The remote manifest's exact JSON text; pass verbatim to [TerritoryManager::apply_update]. | |
var manifestSig | String | The 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
public struct BannerLine: Equatable, Hashable
One line of a visual banner (primary/secondary/sub).
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | Text to display. | |
var maneuverType | String? | Standardised maneuver type for the arrow glyph (e.g. turn). | |
var maneuverModifier | String? | Standardised maneuver modifier (e.g. right). | |
var roundaboutExitDegrees | UInt16? | 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
public struct ChangedLayer: Equatable, Hashable
One layer that a territory update must download.
| Property | Type | Default | Description |
|---|---|---|---|
var kind | String | The layer kind's kebab-case string. | |
var path | String | Path of the layer relative to the package root. | |
var bytes | UInt64 | Layer size in bytes. |
Initialisers and methods
public init(kind: String, path: String, bytes: UInt64)
ChannelInstallResult
Struct · Sources/MapMapKit/Generated/mapmap.swift
public struct ChannelInstallResult: Equatable, Hashable
What [TerritoryManager::install_from_channel] did.
| Property | Type | Default | Description |
|---|---|---|---|
var territory | TerritoryInfo | The installed territory. | |
var layersFetched | UInt32 | How many layer blobs were downloaded on this attempt. | |
var layersReused | UInt32 | How 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 bytesDownloaded | UInt64 | Bytes 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
public struct FasterRouteCandidate: Equatable, Hashable
One candidate route for the remaining journey, summarised from the router's response (a primary route or an alternate).
| Property | Type | Default | Description |
|---|---|---|---|
var id | String? | 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 durationS | Double | The 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
public struct FasterRouteConfig: Equatable, Hashable
Faster-route evaluator configuration, flattened for FFI like
[crate::reroute::RerouteConfig].
| Property | Type | Default | Description |
|---|---|---|---|
var checkIntervalS | Double | Seconds between checks. A check becomes due once this much time has elapsed since the last evaluation (or since the first observation). | |
var minSavingS | UInt32 | Minimum absolute saving in seconds. Candidates saving less are never recommended. | |
var minSavingFrac | Double | Minimum saving as a fraction of the current remaining time (0..1). Both this and min_saving_s must pass. | |
var dismissSuppressS | Double | Seconds a dismissal suppresses further recommendations. Within the window only a saving at least double the dismissed one re-prompts. | |
var maneuverBlackoutS | Double | Seconds-to-next-manoeuvre under which a due check is deferred; the check fires on the first observation clear of the blackout. | |
var enabled | Bool | Whether 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
public struct FasterRouteRecommendation: Equatable, Hashable
A recommendation to switch to a faster candidate route.
| Property | Type | Default | Description |
|---|---|---|---|
var savesS | UInt32 | Estimated saving in seconds versus staying on the current route. | |
var candidateIdx | UInt32 | Index 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var stepAdvanceDistanceM | UInt16 | Advance to the next step when the user is within this many metres of the end of the current step. | |
var minimumHorizontalAccuracyM | UInt16 | Location fixes with worse horizontal accuracy than this (metres) can neither advance a step nor flag a deviation. | |
var routeDeviationThresholdM | Double | The user is off route when further than this many metres from the route line. | |
var snapCourseToRoute | Bool | Snap the reported course to the route line (true, recommended for vehicular navigation) or report the raw course (false). | |
var waypointAdvanceRangeM | Double | A 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
public struct LaneGuidance: Equatable, Hashable
One lane at the upcoming maneuver, for lane-diagram UIs.
| Property | Type | Default | Description |
|---|---|---|---|
var directions | [String] | Turn directions this lane allows (OSRM indication strings, e.g. left, straight, slight right). | |
var active | Bool | Whether guidance recommends this lane for the maneuver. | |
var activeDirection | String? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var originCell | String | Geohash cell of the first committed position. | |
var destCell | String | Geohash cell of the last committed position. | |
var departBucket | String | Coarse 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
public struct Place: Equatable, Hashable
One on-device search result: the matched document's display and context fields plus its position.
| Property | Type | Default | Description |
|---|---|---|---|
var id | String | Stable identifier (e.g. an OSM-derived id). | |
var kind | PlaceKind | What kind of entity this is. | |
var name | String | Primary display name. | |
var housenumber | String? | House number, for [PlaceKind::Address] results. | |
var street | String? | Containing street name, for addresses and POIs. | |
var locality | String? | Containing town or city. | |
var region | String? | Containing county / region. | |
var postcode | String? | Postcode, formatted as displayed (e.g. "SW1A 2AA"). | |
var countryCode | String | ISO 3166-1 alpha-2 country code (e.g. "GB"). | |
var lat | Double | Latitude in decimal degrees (WGS84). | |
var lon | Double | Longitude in decimal degrees (WGS84). | |
var categories | [String] | POI categories (e.g. "fuel", "truck_stop"). Empty for non-POIs. | |
var importance | Float | Rank boost in [0, 1]; larger means more prominent. | |
var distanceM | Double? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var probeFormat | UInt32 | Wire-format version (PROBE_FORMAT). | |
var territory | String? | Territory id the trip was navigated in, when the caller supplies it. | |
var vehicleClass | String? | Vehicle costing class (e.g. truck_40t), a class only, never a registration, VIN or driver identifier. | |
var routeRef | String? | 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 od | OdRecord? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var enabled | Bool | Whether the collector aggregates at all. When false, ProbeCollector ignores every fix and [ProbeCollector::finish] returns an empty batch. | |
var tripEndSuppressionM | Double | Radius in metres around both trip ends within which observations are discarded (see the module's trip-end-suppression note). | |
var minSegmentObservations | UInt32 | Minimum observation count for a segment cell to appear in the batch. | |
var timeBucketMinutes | UInt32 | Width 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 odCellPrecision | UInt8 | Geohash precision (characters) for the origin/destination cells; 5 is roughly a 5 km cell. | |
var collectOd | Bool | Whether 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
public struct RerouteAnchor: Equatable, Hashable
The point and course a recalculated route should depart from.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | Latitude in decimal degrees (WGS84). | |
var lon | Double | Longitude in decimal degrees (WGS84). | |
var courseDeg | Double? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var minConsecutiveOffrouteFixes | UInt32 | Minimum 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 minOffrouteDurationS | Double | Minimum time in seconds the vehicle must have been continuously off route before a reroute is confirmed. | |
var minIntervalBetweenReroutesS | Double | Minimum 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 enabled | Bool | Whether 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
public struct RerouteDecision: Equatable, Hashable
A confirmed reroute: where to route from, where to, and why.
| Property | Type | Default | Description |
|---|---|---|---|
var reason | RerouteReason | Why the reroute was requested. | |
var anchor | RerouteAnchor | The 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
public struct RerouteWaypoint: Equatable, Hashable
One onward waypoint of the active route.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | Latitude in decimal degrees (WGS84). | |
var lon | Double | Longitude in decimal degrees (WGS84). | |
var isBreak | Bool | Whether 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var instruction | String | Written instruction, e.g. Turn right onto Main Street. | |
var maneuverType | UInt32 | Numeric 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 verbalPreTransitionInstruction | String? | Spoken instruction immediately before the transition, when present. | |
var verbalPostTransitionInstruction | String? | Spoken instruction immediately after the transition, when present. | |
var streetNames | [String] | Street names along the maneuver (empty when unnamed). | |
var distanceM | Double | Maneuver length in metres. | |
var durationS | Double | Estimated maneuver time in seconds. | |
var beginShapeIndex | UInt32 | Index into [RouteResult::geometry] where the maneuver starts. | |
var endShapeIndex | UInt32 | Index into [RouteResult::geometry] where the maneuver ends. | |
var roundaboutExitCount | UInt32? | 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
public struct RoutePoint: Equatable, Hashable
A route waypoint.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | Latitude in decimal degrees (WGS84). | |
var lon | Double | Longitude in decimal degrees (WGS84). |
Initialisers and methods
public init(lat: Double, lon: Double)
RouteResult
Struct · Sources/MapMapKit/Generated/mapmap.swift
public struct RouteResult: Equatable, Hashable
Result of an offline route computation.
| Property | Type | Default | Description |
|---|---|---|---|
var summary | RouteSummary | SI 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 valhallaResponseJson | String | The raw Valhalla response JSON (feed this to [GuidanceSession::new]). | |
var osrmResponseJson | String | OSRM 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
public struct RouteSummary: Equatable, Hashable
SI summary of a parsed route.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceM | Double | Total distance in metres. | |
var durationS | Double | Total travel time in seconds. | |
var hasToll | Bool | Whether the route crosses a toll. | |
var hasHighway | Bool | Whether the route uses a highway. | |
var hasFerry | Bool | Whether 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var stepIndex | UInt32 | Zero-based step index within the served route (route_ref). | |
var todBucket | String | Day-of-week × time-of-day bucket, e.g. tue_0745. | |
var observations | UInt32 | Number of fixes folded into this cell. | |
var meanSpeedKmh | Double | Mean speed over the cell, in km/h. | |
var p85SpeedKmh | Double | 85th-percentile speed over the cell, in km/h (exact up to MAX_SPEED_SAMPLE observations, reservoir-estimated beyond). | |
var stoppedS | Double | Seconds spent at or below STOPPED_SPEED_MPS in this cell. | |
var limitDeltaKmh | Double? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | Route-snapped latitude in decimal degrees (WGS84). | |
var lon | Double | Route-snapped longitude in decimal degrees (WGS84). | |
var courseDeg | Double? | 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
public struct SpokenPrompt: Equatable, Hashable
The spoken prompt to synthesise for the upcoming maneuver.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | Plain text for the platform text-to-speech engine. | |
var ssml | String? | SSML form, preferred by TTS engines that support it. | |
var triggerDistanceM | Double | Metres before the maneuver at which to start speaking. | |
var utteranceId | String | Unique 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
public struct TerritoryInfo: Equatable, Hashable
Summary of one installed territory.
| Property | Type | Default | Description |
|---|---|---|---|
var territoryId | String | Stable territory identifier, e.g. "uk". | |
var displayName | String | Human-readable territory name. | |
var version | String | Package semver. | |
var dataTimestamp | String | OSM snapshot timestamp, RFC 3339. | |
var west | Double | Bounding box west edge (degrees). | |
var south | Double | Bounding box south edge (degrees). | |
var east | Double | Bounding box east edge (degrees). | |
var north | Double | Bounding box north edge (degrees). | |
var totalBytes | UInt64 | Total size of all layers in the published package, in bytes, whether or not this install holds them. | |
var installedBytes | UInt64 | Size 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 path | String | Absolute path of the installed package directory. | |
var active | Bool | Whether 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
public struct UpdatePlan: Equatable, Hashable
A differential update plan.
| Property | Type | Default | Description |
|---|---|---|---|
var changed | [ChangedLayer] | Layers that must be downloaded. | |
var installedBytes | UInt64 | Uncompressed 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
public struct UpdateResult: Equatable, Hashable
What [TerritoryManager::apply_update] did.
| Property | Type | Default | Description |
|---|---|---|---|
var territory | TerritoryInfo | The territory after the update. | |
var previousVersion | String | The version that was installed before the update. | |
var layersFetched | UInt32 | How many layer blobs were downloaded on this attempt. | |
var layersReused | UInt32 | How 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 bytesDownloaded | UInt64 | Bytes 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
public struct VisualBanner: Equatable, Hashable
The visual banner to display for the upcoming maneuver.
| Property | Type | Default | Description |
|---|---|---|---|
var primary | BannerLine | Main line: what to do / where you're going. | |
var secondary | BannerLine? | Optional second line. | |
var sub | BannerLine? | Optional sub banner (typically the lane diagram). | |
var triggerDistanceM | Double | Metres before the maneuver at which to start displaying. | |
var drivingSide | String? | 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 roadRef | String? | 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 country | String? | 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 subdivision | String? | 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 roadClass | String? | 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
public enum AdrDecision: Equatable, Hashable
Outcome of a tunnel-entry check, mirroring [sn_adr::Decision].
| Case | Description |
|---|---|
allowed | Passage is permitted. |
blocked(reason: String) | Passage is forbidden. |
AdrTunnelCategory
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum AdrTunnelCategory: Equatable, Hashable
ADR tunnel category A–E (ascending restrictiveness), mirroring
[sn_adr::TunnelCategory].
| Case | Description |
|---|---|
a | No dangerous-goods restriction. |
b | Restriction for goods which may lead to a very large explosion. |
c | … or a large explosion or large toxic release. |
d | … or a large fire. |
e | Restriction for nearly all dangerous goods. |
AdrTunnelCode
Enum · Sources/MapMapKit/Generated/mapmap.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.
| Case | Description |
|---|---|
noCode | ADR (, ), passage permitted through all tunnels. |
b | Code B. |
b1000c | Code B1000C. |
bd | Code B/D. |
be | Code B/E. |
c | Code C. |
c5000d | Code C5000D. |
cd | Code C/D. |
ce | Code C/E. |
d | Code D. |
de | Code D/E. |
e | Code E. |
ChannelInstallOutcome
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum ChannelInstallOutcome: Equatable, Hashable
How a channel install ended.
| Case | Description |
|---|---|
installed(result: ChannelInstallResult) | The package verified and was promoted. |
cancelled | The CancelToken was tripped before promotion. Nothing was installed; verified layers stay parked for the next attempt. |
CostingModel
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum CostingModel: Equatable, Hashable
Valhalla costing model, mirroring [sn_valhalla::valhalla::Costing].
| Case | Description |
|---|---|
auto | Standard car costing. |
truck | Truck costing (required when an ADR profile is supplied). |
bus | Bus costing. |
motorScooter | Motor scooter costing. |
motorcycle | Motorcycle costing. |
bicycle | Bicycle costing. |
pedestrian | Pedestrian costing. |
FetchError
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum FetchError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError
A transport failure thrown by a foreign LayerFetcher
implementation.
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? | Human-readable description of the failure. |
| Case | Description |
|---|---|
Transport(message: String) | The download failed (network, storage, cancelled, …). |
GuidanceUpdate
Enum · Sources/MapMapKit/Generated/mapmap.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.
| Case | Description |
|---|---|
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. |
arrived | The 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
public enum InstallOutcome: Equatable, Hashable
How a cancellable install ended.
| Case | Description |
|---|---|
installed(territory: TerritoryInfo) | The package verified and was promoted. |
cancelled | The CancelToken was tripped before promotion. Nothing was installed; staging was removed. |
InstructionSeverity
Enum · Sources/MapMapKit/Generated/mapmap.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 aBlockeddecision, the hook platform layers use whencheck_tunnelfires 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.
| Case | Description |
|---|---|
info | A normal manoeuvre announcement. |
warning | Approaching a restriction (toll booth, ferry boarding/landing). |
critical | A prohibition: ADR tunnel block or a gate across the carriageway. |
MapLayerKind
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum MapLayerKind: Equatable, Hashable
Map layer kind, mirroring [sn_package::LayerKind].
| Case | Description |
|---|---|
valhallaTiles | Valhalla routing tile tree. |
pmtiles | PMTiles render layer. |
geocodeIndex | Tantivy geocoding index. |
poiSidecar | Proprietary POI sidecar database. |
extra(name: String) | Any other layer kind, by its manifest string. |
NavCoreError
Enum · Sources/MapMapKit/Generated/mapmap.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.
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? | Human-readable description. |
| Case | Description |
|---|---|
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
public enum PlaceKind: Equatable, Hashable
The kind of entity a Place describes, mirroring
[sn_geocode::DocKind].
| Case | Description |
|---|---|
address | A single addressable building or unit (housenumber + street). |
street | A named street or road. |
locality | A town, city, village or suburb. |
poi | A point of interest (fuel station, truck stop, museum, …). |
postcode | A postcode centroid (full or outward code). |
ProbeEvent
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum ProbeEvent: Equatable, Hashable
A coarse, time-bucketed event within a trip.
| Case | Description |
|---|---|
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
public enum RerouteReason: Equatable, Hashable
Why a reroute was requested.
| Case | Description |
|---|---|
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
public enum RerouteState: Equatable, Hashable
The controller's state after the most recent update, for UI and telemetry.
| Case | Description |
|---|---|
monitoring | On 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. |
rerouteNeeded | A reroute is confirmed for this update; the accompanying RerouteDecision should be routed. Reported exactly once per confirmed departure. |
coolingDown | Off route and confirmed again, but suppressed because a reroute fired within [RerouteConfig::min_interval_between_reroutes_s]. |
SpeedLimit
Enum · Sources/MapMapKit/Generated/mapmap.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.
| Case | Description |
|---|---|
known(kmh: Double) | A known posted limit, normalised to kilometres per hour regardless of the unit the route expressed it in. |
unlimited | The road is de-restricted (Mapbox maxspeed none; OSM maxspeed=none, e.g. a German autobahn), show a "no limit" badge, do not warn. |
unknown | A 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
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).
| Case | Description |
|---|---|
light | The light (day) style, also the package default. |
dark | The dark (night) style. |
UpdateOutcome
Enum · Sources/MapMapKit/Generated/mapmap.swift
public enum UpdateOutcome: Equatable, Hashable
How a cancellable update ended.
| Case | Description |
|---|---|
applied(result: UpdateResult) | The update verified and was swapped in. |
cancelled | The 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
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
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_mdefaults to0.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
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-relativerel_path(e.g.territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local filedest_path.expected_blake3is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouter
Protocol · Sources/MapMapKit/Generated/mapmap.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
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.arriveddistinguishes 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 toPOST /v1/probe, orNonewhen 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_mpsis the device's reported ground speed when available (preferred); passNoneto 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
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 throughfetcher, 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 aCancelToken. 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. Givefetcherthe 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 reportsCancelledrather 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_jsonmust be the exact bytes served asindex.jsonandindex_sig_base64the content ofindex.json.sig; the remote manifest is fetched and verified throughfetcher. ReturnsNonewhen 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 aCancelToken. 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:omitnames the kinds to leave out (e.g.PmtilesandExtra("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 inomitis never requested, so it is never metered and never stored.index_json/index_sig_base64are the exact served bytes ofindex.jsonandindex.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.snpkgarchive (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 aCancelToken. 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.snpkgarchive. 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 returnedTerritorySearchholds 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 tonew_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'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<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. Theglyphsendpoint 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
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).nearbiases ranking towards the given point and fills each result'sdistance_m;limitcaps the number of hits.
Functions (MapMap core bindings (generated))
buildOfflineRouteRequest, checkTunnel, forbiddenCategories, parseRouteResult, routeOffline, styleForNavigation, styleWithBuildings3d
buildOfflineRouteRequest
Function · Sources/MapMapKit/Generated/mapmap.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
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
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
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
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
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
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
open class AndAdvanceConditions: AndAdvanceConditionsProtocol, @unchecked Sendable
Advance if all of the conditions are met (AND).
DistanceEntryAndExitCondition
Class · Sources/MapMapKit/Generated/ferrostar.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
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
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
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
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.
NavigationCacheImpl
Class · Sources/MapMapKit/Generated/ferrostar.swift
open class NavigationCacheImpl: NavigationCache, @unchecked Sendable
Initialisers and methods
open func save(record: Data)open func load() -> Data?open func delete()
NavigationController
Class · Sources/MapMapKit/Generated/ferrostar.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.
NavigationObserverImpl
Class · Sources/MapMapKit/Generated/ferrostar.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)
NavigationRecorder
Class · Sources/MapMapKit/Generated/ferrostar.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 -> Stringopen func onAdvanceToNextStep(state: NavState)open func onGetInitialState(state: NavState)open func onRouteAvailable(route: Route)open func onUserLocationUpdate(location: UserLocation, state: NavState)
NavigationReplay
Class · Sources/MapMapKit/Generated/ferrostar.swift
open class NavigationReplay: NavigationReplayProtocol, @unchecked Sendable
A wrapper around NavigationRecording to facilitate replaying the event stream.
NavigationSession
Class · Sources/MapMapKit/Generated/ferrostar.swift
open class NavigationSession: NavigationSessionProtocol, @unchecked Sendable
Initialisers and methods
public convenience init(controller: Navigator, observers: [NavigationObserver])open func advanceToNextStep(state: NavState) -> NavStateopen func getInitialState(location: UserLocation) -> NavStateopen func route() -> Routeopen func updateUserLocation(location: UserLocation, state: NavState) -> NavState
NavigationSessionCache
Class · Sources/MapMapKit/Generated/ferrostar.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)
Navigator
Class · Sources/MapMapKit/Generated/ferrostar.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() -> Routeopen func getInitialState(location: UserLocation) -> NavStateopen func advanceToNextStep(state: NavState) -> NavStateopen func updateUserLocation(location: UserLocation, state: NavState) -> NavState
OrAdvanceConditions
Class · Sources/MapMapKit/Generated/ferrostar.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:
- A short circuit detecting if the user has exceeded a large distance from the current step.
- A default advance behavior.
RouteAdapter
Class · Sources/MapMapKit/Generated/ferrostar.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 -> RouteRequestopen func parseResponse(response: Data) throws -> [Route]
RouteDeviationDetectorImpl
Class · Sources/MapMapKit/Generated/ferrostar.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 circuitingStepAdvanceCondition'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
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
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
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
public struct BoundingBox: Equatable, Hashable, Codable
A geographic bounding box defined by its corners.
| Property | Type | Default | Description |
|---|---|---|---|
var sw | GeographicCoordinate | The southwest corner of the bounding box. | |
var ne | GeographicCoordinate | The northeast corner of the bounding box. |
Initialisers and methods
public init(sw: GeographicCoordinate, ne: GeographicCoordinate)
Congestion
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct Congestion: Equatable, Hashable, Codable
Details about congestion for an incident.
| Property | Type | Default | Description |
|---|---|---|---|
var value | UInt8 | The 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
public struct CourseOverGround: Equatable, Hashable, Codable
The direction in which the user/device is observed to be traveling.
| Property | Type | Default | Description |
|---|---|---|---|
var degrees | UInt16 | The 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 accuracy | UInt16? | 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
public struct GeographicCoordinate: Equatable, Hashable, Codable
A geographic coordinate in WGS84.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | The latitude (in degrees). | |
var lng | Double | The Longitude (in degrees). |
Initialisers and methods
public init(lat: Double, lng: Double)
Heading
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct Heading: Equatable, Hashable, Codable
The heading of the user/device.
| Property | Type | Default | Description |
|---|---|---|---|
var trueHeading | UInt16 | The heading in degrees relative to true north. | |
var accuracy | UInt16 | The platform specific accuracy of the heading value. | |
var timestamp | Date | The 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
public struct Incident: Equatable, Hashable, Codable
An incident affecting the free flow of traffic, such as constructions, accidents, and congestion.
| Property | Type | Default | Description |
|---|---|---|---|
var id | String | A unique identifier for the incident. | |
var incidentType | IncidentType | The type of incident. | |
var description | String? | A short description of the incident. | |
var longDescription | String? | A longer description of the incident. | |
var creationTime | UtcDateTime? | The time at which the incident was last created. NB: This can change throughout the life of the incident. | |
var startTime | UtcDateTime? | The time at which the incident started or is expected to start (ex: planned closure). | |
var endTime | UtcDateTime? | The time at which the incident ended or is expected to end. | |
var impact | Impact? | The level of impact to traffic. | |
var lanesBlocked | [BlockedLane] | Lanes which are blocked by the incident. | |
var congestion | Congestion? | Info about the amount of congestion on the road around the incident. | |
var closed | Bool? | Is the road completely closed? | |
var geometryIndexStart | UInt64 | The index into the RouteStep geometry where the incident starts. | |
var geometryIndexEnd | UInt64? | The index into the RouteStep geometry where the incident ends. | |
var subType | String? | Optional additional information about the type of incident (free-form text). | |
var subTypeDescription | String? | Optional descriptions about the type of incident (free-form text). | |
var iso31661Alpha2 | String? | The ISO 3166-1 alpha-2 code of the country in which the incident occurs. | |
var iso31661Alpha3 | String? | 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 bbox | BoundingBox? | 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
public struct LaneInfo: Equatable, Hashable, Codable
The content of a visual instruction.
| Property | Type | Default | Description |
|---|---|---|---|
var active | Bool | ||
var directions | [String] | ||
var activeDirection | String? |
Initialisers and methods
public init(active: Bool, directions: [String], activeDirection: String?)
LocationSimulationState
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct LocationSimulationState: Equatable, Hashable, Codable
The current state of the simulation.
| Property | Type | Default | Description |
|---|---|---|---|
var currentLocation | UserLocation | ||
var remainingLocations | [GeographicCoordinate] | ||
var bias | LocationBias |
Initialisers and methods
public init(currentLocation: UserLocation, remainingLocations: [GeographicCoordinate], bias: LocationBias)
NavigationCachingConfig
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct NavigationCachingConfig: Equatable, Hashable, Codable
| Property | Type | Default | Description |
|---|---|---|---|
var cacheIntervalSeconds | Int64 | ||
var maxAgeSeconds | Int64 |
Initialisers and methods
public init(cacheIntervalSeconds: Int64, maxAgeSeconds: Int64)
NavigationControllerConfig
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct NavigationControllerConfig
| Property | Type | Default | Description |
|---|---|---|---|
var waypointAdvance | WaypointAdvanceMode | Configures when navigation advances to the next waypoint in the route. | |
var stepAdvanceCondition | StepAdvanceCondition | Configures when navigation advances to the next step in the route. | |
var arrivalStepAdvanceCondition | StepAdvanceCondition | A 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 routeDeviationTracking | RouteDeviationTracking | Configures 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 snappedLocationCourseFiltering | CourseFiltering | Configures 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)
NavigationRecordingEvent
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct NavigationRecordingEvent: Equatable, Hashable, Codable
An event that occurs during navigation.
This is used for the optional session recording / telemetry.
| Property | Type | Default | Description |
|---|---|---|---|
var timestamp | Int64 | The timestamp of the event in milliseconds since Jan 1, 1970 UTC. | |
var eventData | NavigationRecordingEventData | Data associated with the event. |
Initialisers and methods
public init(timestamp: Int64, eventData: NavigationRecordingEventData)
NavigationSessionSnapshot
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct NavigationSessionSnapshot: Equatable, Hashable, Codable
| Property | Type | Default | Description |
|---|---|---|---|
var savedAt | UtcDateTime | ||
var route | Route | ||
var tripState | TripState? |
Initialisers and methods
public init(savedAt: UtcDateTime, route: Route, tripState: TripState?)
NavState
Struct · Sources/MapMapKit/Generated/ferrostar.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.
| Property | Type | Default | Description |
|---|---|---|---|
var tripState | TripState | ||
var stepAdvanceCondition | StepAdvanceCondition |
Initialisers and methods
public init(tripState: TripState, stepAdvanceCondition: StepAdvanceCondition)
OsrmWaypointProperties
Struct · Sources/MapMapKit/Generated/ferrostar.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.
| Property | Type | Default | Description |
|---|---|---|---|
var name | String? | The name of the street that the waypoint snapped to. | |
var distance | Double? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var geometry | [GeographicCoordinate] | ||
var bbox | BoundingBox | ||
var distance | Double | The 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var geometry | [GeographicCoordinate] | The full route geometry for this step. | |
var distance | Double | The distance, in meters, to travel along the route after the maneuver to reach the next step. | |
var duration | Double | The estimated duration, in seconds, that it will take to complete this step. | |
var roadName | String? | The name of the road being traveled on (useful for certain UI styles). | |
var exits | [String] | A list of exits (name or number). | |
var instruction | String | A 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 drivingSide | DrivingSide? | 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 roundaboutExitNumber | UInt8? | 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
public struct SerializableNavState: Equatable, Hashable, Codable
| Property | Type | Default | Description |
|---|---|---|---|
var tripState | TripState | ||
var stepAdvanceCondition | SerializableStepAdvanceCondition |
Initialisers and methods
public init(tripState: TripState, stepAdvanceCondition: SerializableStepAdvanceCondition)
Speed
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct Speed: Equatable, Hashable, Codable
The speed of the user from the location provider.
| Property | Type | Default | Description |
|---|---|---|---|
var value | Double | The user's speed in meters per second. | |
var accuracy | Double? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | Plain-text instruction which can be synthesized with a TTS engine. | |
var ssml | String? | Speech Synthesis Markup Language, which should be preferred by clients capable of understanding it. | |
var triggerDistanceBeforeManeuver | Double | How far (in meters) from the upcoming maneuver the instruction should start being spoken. | |
var utteranceId | Uuid | A 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var shouldAdvance | Bool | The step should be advanced. | |
var nextIteration | StepAdvanceCondition | The 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
public struct TripProgress: Equatable, Hashable, Codable
High-level state describing progress through a route.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceToNextManeuver | Double | The distance to the next maneuver, in meters. | |
var distanceRemaining | Double | The 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 durationRemaining | Double | The 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
public struct TripSummary: Equatable, Hashable, Codable
Information pertaining to the user's full navigation trip. This includes simple stats like total duration and distance.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceTraveled | Double | The total raw distance traveled in the trip, in meters. | |
var snappedDistanceTraveled | Double | The total snapped distance traveled in the trip, in meters. | |
var startedAt | UtcDateTime | When the trip was started. | |
var endedAt | UtcDateTime? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var coordinates | GeographicCoordinate | ||
var horizontalAccuracy | Double | The estimated accuracy of the coordinate (in meters) | |
var courseOverGround | CourseOverGround? | ||
var timestamp | Date | ||
var speed | Speed? |
Initialisers and methods
public init(coordinates: GeographicCoordinate, horizontalAccuracy: Double, courseOverGround: CourseOverGround?, timestamp: Date, speed: Speed?)
ValhallaLocationSearchFilter
Struct · Sources/MapMapKit/Generated/ferrostar.swift
public struct ValhallaLocationSearchFilter: Equatable, Hashable, Codable
A set of optional filters to exclude candidate edges based on their attributes.
| Property | Type | Default | Description |
|---|---|---|---|
var excludeTunnel | Bool? | Whether to exclude roads marked as tunnels. | |
var excludeBridge | Bool? | Whether to exclude roads marked as bridges. | |
var excludeTolls | Bool? | Whether to exclude roads with tolls. | |
var excludeFerry | Bool? | Whether to exclude ferries. | |
var excludeRamp | Bool? | Whether to exclude roads marked as ramps. | |
var excludeClosures | Bool? | Whether to exclude roads marked as closed due to a live traffic closure. | |
var minRoadClass | ValhallaRoadClass? | The lowest road class allowed. | |
var maxRoadClass | ValhallaRoadClass? | The highest road class allowed. | |
var level | Float? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var heading | UInt16? | 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 headingTolerance | UInt16? | 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 minimumReachability | UInt16? | 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 radius | UInt16? | 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 preferredSide | ValhallaWaypointPreferredSide? | 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 displayCoordinate | GeographicCoordinate? | 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 searchCutoff | UInt32? | 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 nodeSnapTolerance | UInt16? | 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 streetSideTolerance | UInt16? | 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 streetSideMaxDistance | UInt16? | 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 streetSideCutoff | ValhallaRoadClass? | 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 searchFilter | ValhallaLocationSearchFilter? | A set of optional filters to exclude candidate edges based on their attributes. | |
var allowUturns | Bool? | `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 name | String? | 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
public struct VisualInstruction: Equatable, Hashable, Codable
An instruction for visual display (usually as banners) at a specific point along a RouteStep.
| Property | Type | Default | Description |
|---|---|---|---|
var primaryContent | VisualInstructionContent | The primary instruction content. This is usually given more visual weight. | |
var secondaryContent | VisualInstructionContent? | Optional secondary instruction content. | |
var subContent | VisualInstructionContent? | Optional sub-maneuver instruction content. | |
var triggerDistanceBeforeManeuver | Double | How 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
public struct VisualInstructionContent: Equatable, Hashable, Codable
The content of a visual instruction.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | The text to display. | |
var maneuverType | ManeuverType? | A standardized maneuver type (if any). | |
var maneuverModifier | ManeuverModifier? | A standardized maneuver modifier (if any). | |
var roundaboutExitDegrees | UInt16? | 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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var coordinate | GeographicCoordinate | ||
var kind | WaypointKind | ||
var properties | Data? | 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
public enum BlockedLane: Equatable, Hashable, Codable
The lane type blocked by the incident.
| Case | Description |
|---|---|
left | |
leftCenter | |
leftTurnLane | |
center | |
right | |
rightCenter | |
rightTurnLane | |
hov |
CourseFiltering
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum CourseFiltering: Equatable, Hashable, Codable
Controls filtering/post-processing of user course by the NavigationController.
| Case | Description |
|---|---|
snapToRoute | Snap the user's course to the current step's linestring using the next index in the step's geometry. |
raw | Use the raw course as reported by the location provider with no processing. |
DeviationCalculationPolicy
Enum · Sources/MapMapKit/Generated/ferrostar.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.
| Case | Description |
|---|---|
always | Always evaluate, regardless of deviation status. |
whileOnRoute | Evaluate 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. |
whileOnCurrentStep | Evaluate 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
public enum DeviationKind: Equatable, Hashable, Codable
The kind of deviation from the expected route.
| Case | Description |
|---|---|
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
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).
| Case | Description |
|---|---|
left | |
right |
GraphHopperVoiceUnits
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum GraphHopperVoiceUnits: Equatable, Hashable, Codable
| Case | Description |
|---|---|
metric | |
imperial |
Impact
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum Impact: Equatable, Hashable, Codable
The impact of the incident that has occurred.
| Case | Description |
|---|---|
unknown | |
critical | |
major | |
minor | |
low |
IncidentType
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum IncidentType: Equatable, Hashable, Codable
The type of incident that has occurred.
| Case | Description |
|---|---|
accident | |
congestion | |
construction | |
disabledVehicle | |
laneRestriction | |
massTransit | |
miscellaneous | |
otherNews | |
plannedEvent | |
roadClosure | |
roadHazard | |
weather |
InstantiationError
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum InstantiationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
OptionsJsonParseError |
LocationBias
Enum · Sources/MapMapKit/Generated/ferrostar.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.
| Case | Description |
|---|---|
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. |
none | No 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
public enum ManeuverModifier: Equatable, Hashable, Codable
Additional information to further specify a ManeuverType.
| Case | Description |
|---|---|
uTurn | |
sharpRight | |
right | |
slightRight | |
straight | |
slightLeft | |
left | |
sharpLeft |
ManeuverType
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum ManeuverType: Equatable, Hashable, Codable
The broad class of maneuver to perform.
This is usually combined with ManeuverModifier in VisualInstructionContent.
| Case | Description |
|---|---|
turn | |
newName | |
depart | |
arrive | |
merge | |
onRamp | |
offRamp | |
fork | |
endOfRoad | |
`continue` | |
roundabout | |
rotary | |
roundaboutTurn | |
notification | |
exitRoundabout | |
exitRotary |
ModelError
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum ModelError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
PolylineGenerationError(error: String) |
NavigationRecordingEventData
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum NavigationRecordingEventData: Equatable, Hashable, Codable
The event type.
For full replayability, we record things like rerouting, and not just location updates.
| Case | Description |
|---|---|
stateUpdate(tripState: TripState, stepAdvanceCondition: SerializableStepAdvanceCondition) | |
routeUpdate(route: Route) |
ParsingError
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum ParsingError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
InvalidRouteObject(error: String) | |
InvalidGeometry(error: String) | |
MalformedAnnotations(error: String) | |
InvalidStatusCode(code: String, description: String?) | |
UnknownParsingError |
RecordingError
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum RecordingError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
A session recording error.
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
SerializationError(error: String) | Error during serialization. |
RecordingNotEnabled | Recording is not enabled for this controller. |
DeserializationError(error: String) | Error during deserialization. |
RouteDeviation
Enum · Sources/MapMapKit/Generated/ferrostar.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.
| Case | Description |
|---|---|
noDeviation | The 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
public enum RouteDeviationTracking
Determines if the user has deviated from the expected route.
| Case | Description |
|---|---|
none | No 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
public enum RouteRequest: Equatable, Hashable, Codable
A route request generated by a RouteRequestGenerator.
| Case | Description |
|---|---|
httpPost(url: String, headers: [String: String], body: Data) | |
httpGet(url: String, headers: [String: String]) |
RoutingRequestGenerationError
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum RoutingRequestGenerationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
NotEnoughWaypoints | |
JsonError | |
UnknownRequestGenerationError |
SerializableStepAdvanceCondition
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum SerializableStepAdvanceCondition: Equatable, Hashable, Codable
| Case | Description |
|---|---|
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
public enum SimulationError: Swift.Error, Equatable, Hashable, Codable, Foundation.LocalizedError
| Property | Type | Default | Description |
|---|---|---|---|
var errorDescription | String? |
| Case | Description |
|---|---|
PolylineError(error: String) | Errors decoding the polyline string. |
NotEnoughPoints | Not enough points in the input. |
TripState
Enum · Sources/MapMapKit/Generated/ferrostar.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.
| Case | Description |
|---|---|
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
public enum ValhallaRoadClass: Equatable, Hashable, Codable
A road class in the Valhalla taxonomy.
These are ordered from highest (fastest travel speed) to lowest.
| Case | Description |
|---|---|
motorway | |
trunk | |
primary | |
secondary | |
tertiary | |
unclassified | |
residential | |
serviceOther |
ValhallaWaypointPreferredSide
Enum · Sources/MapMapKit/Generated/ferrostar.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
samewill 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
samewill only allow leaving or arriving at a location such that it is on your left.
| Case | Description |
|---|---|
same | You must depart from or arrive at the location on the same side as you drive. |
opposite | You must depart from or arrive at the location on the opposite side as you drive. |
either | No preference; you can depart or arrive from any direction. |
WaypointAdvanceMode
Enum · Sources/MapMapKit/Generated/ferrostar.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!
| Case | Description |
|---|---|
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
public enum WaypointKind: Equatable, Hashable, Codable
Describes characteristics of the waypoint for routing purposes.
| Case | Description |
|---|---|
`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]. |
via | A waypoint that is simply passed through, but will not have any arrival or departure instructions. |
WellKnownRouteProvider
Enum · Sources/MapMapKit/Generated/ferrostar.swift
public enum WellKnownRouteProvider: Equatable, Hashable, Codable
Configurations for built-in route providers.
| Case | Description |
|---|---|
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
public protocol AndAdvanceConditionsProtocol: AnyObject, Sendable
Advance if all of the conditions are met (AND).
DistanceEntryAndExitConditionProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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
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
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
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
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.
NavigationCache
Protocol · Sources/MapMapKit/Generated/ferrostar.swift
public protocol NavigationCache: AnyObject, Sendable
Initialisers and methods
func save(record: Data)func load() -> Data?func delete()
NavigationControllerProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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.
NavigationObserver
Protocol · Sources/MapMapKit/Generated/ferrostar.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)
NavigationRecorderProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.swift
public protocol NavigationRecorderProtocol: AnyObject, Sendable
Initialisers and methods
func getEvents() -> [NavigationRecordingEvent]func getRecordingJson() throws -> Stringfunc onAdvanceToNextStep(state: NavState)func onGetInitialState(state: NavState)func onRouteAvailable(route: Route)func onUserLocationUpdate(location: UserLocation, state: NavState)
NavigationReplayProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.swift
public protocol NavigationReplayProtocol: AnyObject, Sendable
A wrapper around NavigationRecording to facilitate replaying the event stream.
NavigationSessionCacheProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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)
NavigationSessionProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.swift
public protocol NavigationSessionProtocol: AnyObject, Sendable
Initialisers and methods
func advanceToNextStep(state: NavState) -> NavStatefunc getInitialState(location: UserLocation) -> NavStatefunc route() -> Routefunc updateUserLocation(location: UserLocation, state: NavState) -> NavState
NavigatorProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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() -> Routefunc getInitialState(location: UserLocation) -> NavStatefunc advanceToNextStep(state: NavState) -> NavStatefunc updateUserLocation(location: UserLocation, state: NavState) -> NavState
OrAdvanceConditionsProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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:
- A short circuit detecting if the user has exceeded a large distance from the current step.
- A default advance behavior.
RouteAdapterProtocol
Protocol · Sources/MapMapKit/Generated/ferrostar.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 -> RouteRequestfunc parseResponse(response: Data) throws -> [Route]
RouteDeviationDetector
Protocol · Sources/MapMapKit/Generated/ferrostar.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 circuitingStepAdvanceCondition'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
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
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
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
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
public func createFerrostarLogger()
createNavigationSession
Function · Sources/MapMapKit/Generated/ferrostar.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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Type alias · Sources/MapMapKit/Generated/ferrostar.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
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
Class · Sources/MapMapValhalla/ValhallaMobileRouter.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 avalhalla.jsonwhosemjolnir.tile_dirpoints at the territory's Valhalla tile layer.public static func fromConfig(_ configFile: URL) throws -> ValhallaMobileRouter: Create a router from an existingvalhalla.jsonconfig 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 underscratchDir(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) -> Stringpublic func close(): Release the native engine and the mapped tiles. Routing after this returns an error envelope.
Example
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
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.
| Property | Type | Default | Description |
|---|---|---|---|
var isWaitingForConfiguration | true 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 interfaceController | CPInterfaceController? | ||
var carWindow | CPWindow? | ||
var mapTemplate | CPMapTemplate? | ||
var scaleAdjuster | CarPlayWindowScaleAdjuster? | ||
var activity | CarPlayActivity | .browsing | |
var navigationSession | CPNavigationSession? | 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 sessionConfiguration | CPSessionConfiguration? | 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 delegate | CarPlayManagerDelegate? |
Initialisers and methods
public override init()public func sceneConnected(interfaceController: CPInterfaceController, window: CPWindow): ForwardtemplateApplicationScene(_:didConnectInterfaceController:toWindow:)here. Creates the rootCPMapTemplate, sets it as the scene's root template, and, only oncewindowis 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 ininit.public func sceneDisconnected(): ForwardtemplateApplicationScene(_: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 fortrip(CPMapTemplate.showRouteChoicesPreview). Call once route(s) have been computed for a chosen destination.public func startTrip(_ trip: CPTrip, using routeChoice: CPRouteChoice) -> CPNavigationSession?: Start guidance forrouteChoice. Ends any previous session first, there is only ever one activenavigationSession.public func updateNavigationState(_ state: NavigationState, units: CarPlayDistanceUnits = .localeDefault, locale: Locale = .current): Push the latestNavigationStatefrom yourNavigationEngineonto the active session. No-op if there is no active trip.public func stopTrip(cancelled: Bool): End the active trip, if any. - Parameter cancelled:truefor a driver/system cancellation (cancelTrip());falsefor 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), sinceCarPlayManagerDelegateis asked fresh each time.
Example
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
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
// 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
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).
| Property | Type | Default | Description |
|---|---|---|---|
let measurement | Measurement<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
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.
| Property | Type | Default | Description |
|---|---|---|---|
let carScreenNativeScale | CGFloat | The native scale (points → pixels) of the screen the CarPlay window is actually presented on. | |
let phoneScreenNativeScale | CGFloat | The 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 correctionFactor | CGFloat | Multiply 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: theCPWindowsupplied byCPTemplateApplicationSceneDelegate.templateApplicationScene(_:didConnectInterfaceController:toWindow:). Must already be attached to its scene (has a non-defaultscreen). - phoneScreen: the phone's own main screen. Defaults toUIScreen.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'scontentScaleFactordirectly. Suitable for plainUIView/CALayer-backed renderers; MapLibre'sMLNMapView(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
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.
| Property | Type | Default | Description |
|---|---|---|---|
let text | String | Text 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 tier | String | Tier 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 country | String | ISO 3166-1 alpha-2 of the profile that resolved it, "" when unknown. | |
let a11yLabel | String | Spoken label ("Motorway M25", "Interstate 95"); English only for now, like the canonical table. | |
let template | String? | Shield template id; nil for a text-only ref. | |
let source | String | The 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
public enum BadgeSurface: Sendable
The surface a badge sits on: on dark it gets the white halo of SPEC 3.6.
| Case | Description |
|---|---|
light | |
dark |
CarPlayActivity
Enum · Sources/MapMapCarPlay/CarPlayManagerDelegate.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.
| Case | Description |
|---|---|
browsing | Connected, no destination chosen yet, the map template is showing free browse (pan/zoom) with the host's custom buttons, if any. |
previewingRoutes | One 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
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 sharedAVAudioSessionfor 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: whateverAVAudioSession.setCategory/setActivethrow (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
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.
| Case | Description |
|---|---|
localeDefault | Follow the given locale's measurement system (the default: feet → miles in the US, yards → miles in the UK, metres → kilometres elsewhere). |
imperial | Feet, then miles. |
imperialWithYards | Yards, then miles (UK road-signage convention). |
metric | Metres, then kilometres. |
CarPlayMapButtons
Enum · Sources/MapMapCarPlay/CarPlayMapButtons.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) -> CPMapButtonpublic static func zoomOut(action: @escaping () -> Void) -> CPMapButtonpublic static func recenter(action: @escaping () -> Void) -> CPMapButtonpublic static func toggleMute(isMuted: Bool, action: @escaping () -> Void) -> CPMapButtonpublic static func pan(action: @escaping () -> Void) -> CPMapButton
CPLaneGuidanceConverter
Enum · Sources/MapMapCarPlay/Models/CPLaneGuidance+MapMap.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 aCPLaneGuidancefrom a subBannerLine's lane diagram. Returnsnilbelow iOS 18 (no non-deprecatedCPLaneinitializer) or when there are no lanes to show.
ManeuverGlyph
Enum · Sources/MapMapCarPlay/Models/ManeuverGlyph.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.
| Property | Type | Default | Description |
|---|---|---|---|
static let symbolPointSize | CGFloat | 50 | Point 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, includingnil, is unknown and returnsnil: 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 canonicaliconNameForManeuver(type, modifier, drivingSide)inmap-assets/icons/directions/generate.mjs;ManeuverGlyphTestschecks 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 plaincontinue_uturn, never a guessed ring. Always returns a name with a bundled image.public static func vectorImage(named name: String) -> UIImage?: The bundled vector iconname, unsized, as a template image.public static func image(named name: String, pointSize: CGFloat = symbolPointSize) -> UIImage?: The iconnamerendered from its vector data atpointSize(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 (seeiconName(maneuverType:maneuverModifier:drivingSide:)).public static func cpManeuverType(maneuverType: String?, maneuverModifier: String?) -> CPManeuverType: The nearestCPManeuverType, 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
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, theCPTemplateApplicationSceneDelegate-facing orchestrator: browse → preview → navigate → stop activity states, theCPMapTemplate+ its delegate, and the activeCPNavigationSession.CarPlayManagerDelegate, host hooks: supply the map view controller, customise map buttons, observe camera gestures.CPTrip,CPManeuver,CPTravelEstimatesconverters (this module'sModels/directory), pure value conversions from MapMap's FFI types.CarPlayWindowScaleAdjuster, mitigation for the CarPlay-screen scale bug class (MapLibre Native computes scale fromUIScreen.main, not the CarPlay screen, maplibre-native#3214).CarPlayAudioSession, the exactAVAudioSessionconfiguration voice prompts need on CarPlay.ExampleCarPlaySceneDelegate.swift, a compiled, heavily-commented integration example: Info.plist scene manifest keys, thecom.apple.developer.carplay-mapsentitlement, 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.
| Property | Type | Default | Description |
|---|---|---|---|
static let requiredEntitlement | The 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
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).
| Property | Type | Default | Description |
|---|---|---|---|
static let carPlayMaxSize | CarPlay's limit for a text attachment in a manoeuvre instruction (CPManeuver.attributedInstructionVariants: "The maximum text attachment image size is 64x25 points"). | ||
static let carPlayHeight | CGFloat | 23 | The 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 forrefatheightpoints onsurface, rendered atscalepixels per point;nilwhen 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: withincarPlayMaxSize(a long ref is drawn smaller rather than cropped), with a light variant (no halo) and a dark variant (white halo) registered forUIUserInterfaceStyle, 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?:textwith a road-number badge for each ofrefsthat has one, as CarPlay text attachments;nilwhen 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
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 canonicalroadRefLabel.
Protocols (MapMapCarPlay)
CarPlayManagerDelegate
Protocol · Sources/MapMapCarPlay/CarPlayManagerDelegate.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 ownMLNMapView(MapLibre) instance, styled withstyleForNavigation(styleJson:). Called exactly once per connection, afterwindowhas already been attached to itsCPTemplateApplicationScene(window.screenandwindow.mapButtonSafeAreaLayoutGuideare 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. UsescaleAdjusterto 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'smapButtonsfor the currentCarPlayActivity. Returnnilto keep whateverCarPlayManagerlast set (its default is empty, most apps will want to provide at least a mute toggle viaCarPlayMapButtons).func carPlayManager(_ manager: CarPlayManager, leadingNavigationBarButtonsFor activity: CarPlayActivity) -> [CPBarButton]?: The trailing/leading navigation-bar buttons (e.g. "Cancel", "Go") for the current activity. Returnnilto 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 storerouteChoice.mapMapRouteResultand, once the driver taps "Go" (carPlayManager(_:didStartTrip:using:)), build aNavigationEnginefrom it.func carPlayManager(_ manager: CarPlayManager, didStartTrip trip: CPTrip, using routeChoice: CPRouteChoice): The driver committed to navigatingrouteChoice. Start yourNavigationEnginehere and feed its states back throughCarPlayManager/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 calledCarPlayManager/stopTrip(cancelled:)(e.g. on arrival). Stop yourNavigationEnginehere.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)