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

ai.mapmap:core (Android) reference

Generated from the published ai.mapmap:core 0.8.0 sources (core-0.8.0-sources.jar on Maven Central) by website/scripts/sdk-reference-native.mjs. Do not edit by hand: change the doc comments in the SDK, or the examples in website/content/sdk-reference/android.examples.md, and regenerate.

Every public declaration of the Android library at release 0.8.0, from its published sources jar: the hand-written ai.mapmap API and the generated uniffi.mapmap and uniffi.ferrostar bindings to the Rust core. The guide is Android (Kotlin) in SDKs & installation and the hand-written Android API reference. Requires minSdk 26.

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

316 public declarations across 3 packages: 42 written by hand, 274 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.

Setup used by the examples

kotlin
// build.gradle.kts
dependencies {
    implementation("ai.mapmap:core:0.8.0")
}

Contents

ai.mapmap

Classes (ai.mapmap)

AndroidLocationProvider, AudioFocusPolicy, ChannelSource, ChannelSync.Installed, ChannelSync.Updated, ChannelSync.UpToDate, CorpusFormatException, DriveCorpus, DriveFix, DriveHeader, HttpChannelFetcher, HttpProbeUploader, LocationSample, NavigationEngine, NavigationState, ReplayLocationProvider, SignedChannelIndex, TerritoryStore, TtsStartup, TtsStartup.InitActions, ValhallaMobileRouter, VoiceGuidance, VoiceProsody.Prosody

AndroidLocationProvider

Class · ai/mapmap/nav/AndroidLocationProvider.kt

kotlin
public class AndroidLocationProvider(context: Context, private val minIntervalMs: Long = 1_000L, private val minDistanceM: Float = 0f) : LocationProvider

Live LocationProvider on the platform location stack, no Google Play Services dependency.

Uses LocationManager.FUSED_PROVIDER (the platform fused provider, API 31+) and falls back to LocationManager.GPS_PROVIDER on older devices. Requires ACCESS_FINE_LOCATION to be granted before the flow is collected; the SDK manifest deliberately declares no permissions.

Background collection is subject to the platform's background-location limits and OEM battery management, see android/README.md ("Location permissions and device caveats") before shipping fleet builds.

@param minIntervalMs minimum interval between fixes; 1 Hz default matches vehicular guidance expectations.

PropertyTypeDefaultDescription
val locationsFlow<LocationSample>

Nested: AndroidLocationProvider.Companion.

Example

kotlin
import ai.mapmap.nav.AndroidLocationProvider
import android.content.Context

// Needs ACCESS_FINE_LOCATION granted first.
suspend fun printFixes(context: Context) {
    AndroidLocationProvider(context, minIntervalMs = 1_000L).locations.collect { fix ->
        println("${fix.lat}, ${fix.lon} ±${fix.horizontalAccuracyM}")
    }
}

AudioFocusPolicy

Class · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public class AudioFocusPolicy

Pure audio-focus bookkeeping, unit-testable on any JVM. Transient focus is held across the set of outstanding utterances (TextToSpeech queues with QUEUE_ADD, so several can be in flight) and abandoned only when the last one ends. Focus counts as held only when the platform actually granted the request; a denied request is never "abandoned" later, and the next utterance retries it.

PropertyTypeDefaultDescription
var focusHeldBooleanfalseWhether a granted transient focus request is currently held.
val outstandingCountIntUtterances queued but not yet finished.

Initialisers and methods

  • public fun shouldRequestFocus(): Boolean: Before speaking: whether a focus request should be made now.
  • public fun onSpeakQueued(utteranceId: String, flushedQueue: Boolean, granted: Boolean?): Record utteranceId being handed to the engine. flushedQueue is true for QUEUE_FLUSH prompts (everything previously queued is discarded without callbacks); granted is the focus-request result, or null when no request was made because focus is held.
  • public fun onUtteranceEnded(utteranceId: String?): Boolean: Record an utterance ending (done, error or stop). Returns true when focus should be abandoned now, the last outstanding utterance ended while focus was held.
  • public fun reset(): Boolean: Everything stopped/muted. Returns true when focus should be abandoned.

Example

kotlin
import ai.mapmap.nav.AudioFocusPolicy

// The audio-focus bookkeeping VoiceGuidance runs: request once per burst, abandon after the last utterance.
val focus = AudioFocusPolicy()
fun speak(id: String) {
    val request = focus.shouldRequestFocus()
    focus.onSpeakQueued(id, flushedQueue = false, granted = if (request) true else null)
}
fun done(id: String) {
    if (focus.onUtteranceEnded(id)) println("abandon audio focus")
}

ChannelSource

Class · ai/mapmap/territory/ChannelSource.kt

kotlin
public data class ChannelSource(val indexUrl: String, val indexSigUrl: String, val layerBaseUrl: String)

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

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

PropertyTypeDefaultDescription
val indexUrlString
val indexSigUrlString
val layerBaseUrlString

Nested: ChannelSource.Companion.

ChannelSync.Installed

Class · ai/mapmap/territory/TerritoryStore.kt

kotlin
public data class Installed(val result: ChannelInstallResult) : ChannelSync

The territory was not installed; the channel's latest version now is.

PropertyTypeDefaultDescription
val resultChannelInstallResult

ChannelSync.Updated

Class · ai/mapmap/territory/TerritoryStore.kt

kotlin
public data class Updated(val result: UpdateResult) : ChannelSync

An older version was installed; it was updated in place.

PropertyTypeDefaultDescription
val resultUpdateResult

ChannelSync.UpToDate

Class · ai/mapmap/territory/TerritoryStore.kt

kotlin
public data class UpToDate(val territory: TerritoryInfo) : ChannelSync

Already on the channel's latest version; nothing was downloaded.

PropertyTypeDefaultDescription
val territoryTerritoryInfo

CorpusFormatException

Class · ai/mapmap/replay/DriveCorpus.kt

kotlin
public class CorpusFormatException(message: String) : IllegalArgumentException(message)

A .drive.jsonl document violated the corpus format.

DriveCorpus

Class · ai/mapmap/replay/DriveCorpus.kt

kotlin
public data class DriveCorpus(val header: DriveHeader, val fixes: List<DriveFix>)

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 Kotlin parser enforces the same invariants as the Rust one: supported format version, non-empty name, at least one fix, strictly increasing t_ms, and sane coordinate/channel ranges.

PropertyTypeDefaultDescription
val headerDriveHeader
val fixesList<DriveFix>

Nested: DriveCorpus.Companion.

DriveFix

Class · ai/mapmap/replay/DriveCorpus.kt

kotlin
public data class DriveFix(val tMs: Long, val lat: Double, val lon: Double, val speedMps: Double?, val bearingDeg: Double?, val horizontalAccuracyM: Double?)

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

PropertyTypeDefaultDescription
val tMsLong
val latDouble
val lonDouble
val speedMpsDouble?
val bearingDegDouble?
val horizontalAccuracyMDouble?

DriveHeader

Class · ai/mapmap/replay/DriveCorpus.kt

kotlin
public data class DriveHeader(val formatVersion: Int, val name: String, val description: String, val routeFixture: String, val seed: Long)

Header line of a .drive.jsonl corpus.

PropertyTypeDefaultDescription
val formatVersionInt
val nameString
val descriptionString
val routeFixtureString
val seedLong

HttpChannelFetcher

Class · ai/mapmap/territory/ChannelSource.kt

kotlin
public class HttpChannelFetcher(public val source: ChannelSource, private val apiKey: String? = null, private val cancel: CancelToken? = null, private val onBytes: ((Long) -> Unit)? = null) : LayerFetcher

A blocking HTTPS LayerFetcher for a ChannelSource, on HttpURLConnection (no extra dependency). Call it off the main thread; TerritoryStore does.

@param apiKey sent as Authorization: Bearer <apiKey> (the hosted gateway meters layer downloads against the key's allowance); null for an open mirror. @param cancel polled between chunks, so a tripped token stops a transfer in progress, not only the next one. @param onBytes called with the running total of bytes received.

PropertyTypeDefaultDescription
val sourceChannelSource
var lastFailedStatusInt?nullHTTP status of the last failed request, or null. 401/403 auth, 402 allowance, 404 not found.
val bytesReceivedLongTotal bytes received by this fetcher so far.

Initialisers and methods

  • public fun fetchIndex(): SignedChannelIndex: GET the signed index and its signature, exact bytes.
  • override fun fetch(relPath: String, expectedBlake3: String, destPath: String)

Example

kotlin
import ai.mapmap.territory.ChannelSource
import ai.mapmap.territory.HttpChannelFetcher

// What TerritoryStore.sync(territoryId, source, apiKey) builds for you; use it directly when
// you drive installFromChannel or checkForUpdate yourself. Blocking: call off the main thread.
fun fetchIndex() {
    val fetcher = HttpChannelFetcher(ChannelSource.gateway(), apiKey = "snk_…")
    val index = fetcher.fetchIndex()
    println("${index.json.length} bytes, ${fetcher.bytesReceived} received")
}

HttpProbeUploader

Class · ai/mapmap/nav/ProbeContribution.kt

kotlin
public class HttpProbeUploader @JvmOverloads constructor(baseUrl: String, private val apiKey: String, private val maxAttempts: Int = 4, private val backoffMillis: (Int) -> Long = { attempt -> attempt * 1_000L }, private val executor: ExecutorService = Executors.newSingleThreadExecutor { r -> Thread(r, "mapmap-probe-upload").apply { isDaemon = true } }, private val onResult: (ProbeUploadOutcome) -> Unit = {}) : ProbeUploader, AutoCloseable

Default ProbeUploader: POSTs each body to {baseUrl}/v1/probe with a bearer key, on a small daemon executor, using only the JDK HTTP client, the SDK takes on no third-party HTTP dependency. Transient failures (IO or 5xx) are retried with bounded backoff; permanent ones (400/403/501) are dropped. Close it to release the executor.

@param baseUrl gateway origin, e.g. https://api.mapmap.ai (a trailing slash is tolerated); @param maxAttempts total tries including the first; @param backoffMillis attempt-number → delay before the next try.

Example

kotlin
import ai.mapmap.nav.HttpProbeUploader
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.contributingProbe
import ai.mapmap.nav.LocationProvider
import uniffi.mapmap.ProbeConfig

// Opt-in aggregate probe upload (POST /v1/probe), retried with backoff.
suspend fun driveAndContribute(engine: NavigationEngine, provider: LocationProvider) {
    val uploader = HttpProbeUploader("https://api.mapmap.ai", apiKey = "snk_…")
    engine.navigate(provider)
        .contributingProbe(ProbeConfig(enabled = true), uploader)
        .collect { }
}

LocationSample

Class · ai/mapmap/nav/LocationProvider.kt

kotlin
public data class LocationSample(val lat: Double, val lon: Double, val timestampMs: Long, val speedMps: Double? = null, val bearingDeg: Double? = null, val horizontalAccuracyM: Double? = null)

One position sample fed into guidance.

@property timestampMs milliseconds since the Unix epoch. @property speedMps speed over ground, when the source reports it. @property bearingDeg course over ground, degrees clockwise from true north, [0, 360). @property horizontalAccuracyM estimated 1-sigma horizontal accuracy in metres. Pass the platform value whenever available, the core uses it to gate step advance and deviation detection.

PropertyTypeDefaultDescription
val latDouble
val lonDouble
val timestampMsLong
val speedMpsDouble?null
val bearingDegDouble?null
val horizontalAccuracyMDouble?null

Class · ai/mapmap/nav/NavigationEngine.kt

kotlin
public class NavigationEngine(private val routeResponseJson: String, private val config: GuidanceConfig = GuidanceConfig(), private val dispatcher: CoroutineDispatcher = Dispatchers.Default)

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 coroutines: stream LocationSamples in from any LocationProvider, collect 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 Kotlin artefacts can sit on top of this state (uniffi.ferrostar classes are packaged in this SDK and served by the same native library), but our GuidanceSession remains the state machine, see android/README.md, "Ferrostar boundary".

Initialisers and methods

  • public constructor(route: RouteResult, config: GuidanceConfig = GuidanceConfig(), dispatcher: CoroutineDispatcher = Dispatchers.Default): Build an engine from a route computed by ai.mapmap.routing.OfflineRouting.route.
  • public fun navigate(provider: LocationProvider, manualAdvance: Flow<Unit> = emptyFlow()): Flow<NavigationState>: Run guidance: feed every fix from provider into a fresh native session and emit the resulting states. The flow is cold, each collection starts a new session at the first route step, and completes after arrival. Guidance maths runs on dispatcher. @param manualAdvance emit Unit to force-advance to the next step, the tunnel/no-GNSS escape hatch. Ignored before the first fix. @throws uniffi.mapmap.NavCoreException if the route response cannot start a session (e.g. malformed JSON).
  • public fun totalSteps(): UInt: Total number of steps in the route (including arrival), for progress UIs. Opens a short-lived native session.

Example

kotlin
import ai.mapmap.nav.AndroidLocationProvider
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.VoiceGuidance
import android.content.Context
import kotlinx.coroutines.flow.takeWhile

suspend fun drive(context: Context, routeResponseJson: String) {
    val engine = NavigationEngine(routeResponseJson)
    VoiceGuidance(context, language = "en-GB").use { voice ->
        engine.navigate(AndroidLocationProvider(context))
            .takeWhile { state -> !state.isArrived }
            .collect { state -> voice.handle(state) }
    }
}

Class · ai/mapmap/nav/NavigationState.kt

kotlin
public data class NavigationState(val fix: LocationSample, val update: GuidanceUpdate)

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

GuidanceUpdate is the Rust core's sealed state, Navigating, Arrived or OffRoute, and the single source of truth. This wrapper only adds the triggering sample and display conveniences.

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

ReplayLocationProvider

Class · ai/mapmap/nav/ReplayLocationProvider.kt

kotlin
public class ReplayLocationProvider(private val corpus: DriveCorpus, private val timeScale: Double = 1.0, private val epochStartMs: Long = 0L) : 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.

@param corpus a parsed corpus (see DriveCorpus.parse). @param timeScale playback speed: 1.0 = real time, 2.0 = twice as fast, 0.0 = emit every fix immediately (unit tests). @param epochStartMs epoch milliseconds assigned to the first fix.

PropertyTypeDefaultDescription
val locationsFlow<LocationSample>

Nested: ReplayLocationProvider.Companion.

Example

kotlin
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.ReplayLocationProvider
import ai.mapmap.replay.DriveCorpus
import java.io.File

// Replay a recorded drive through guidance, ten times faster than real time.
suspend fun replay(corpusFile: File, routeResponseJson: String) {
    val corpus = DriveCorpus.parse(corpusFile.readText())
    NavigationEngine(routeResponseJson)
        .navigate(ReplayLocationProvider(corpus, timeScale = 10.0))
        .collect { state -> println(state.update) }
}

SignedChannelIndex

Class · ai/mapmap/territory/ChannelSource.kt

kotlin
public data class SignedChannelIndex(val json: String, val signatureBase64: String)

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

PropertyTypeDefaultDescription
val jsonString
val signatureBase64String

TerritoryStore

Class · ai/mapmap/territory/TerritoryStore.kt

kotlin
public class TerritoryStore(private val rootDir: File, private val verifyingKeyHex: String, private val dispatcher: CoroutineDispatcher = Dispatchers.IO, private val regionKeyHex: String? = null) : AutoCloseable

Coroutine-friendly 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. All calls hop to dispatcher (IO by default), installs read whole archives and must never run on the main thread.

territories is a hot StateFlow of the installed set; it refreshes after every mutating call and on refresh.

Installs are cancellable. The overloads taking a CancelToken (from the core) can be stopped from any thread by calling cancel() on it, and they also trip the token when the calling coroutine is cancelled, so a plain job.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.HOSTED_REGION_KEY_HEX 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.

@param rootDir directory the store owns; created on first use. @param verifyingKeyHex the factory signing key's public half, 64 hex characters. Baked into the app at build time, treat it like a pin. @param regionKeyHex the region signing key's public half, 64 hex characters, or null to refuse custom regions. Pinned like the factory key; never read from the network.

PropertyTypeDefaultDescription
val acceptsCustomRegionsBooleanWhether this store was given a region key, and so can install custom regions.
val territoriesStateFlow<List<TerritoryInfo>>The installed territories, refreshed after every mutating call.

Initialisers and methods

  • public suspend fun refresh(): List<TerritoryInfo>: Re-read the installed set from disk and emit it on territories.
  • public suspend fun install(snpkg: File): TerritoryInfo: Install a packed .snpkg archive. Verify-then-promote: a package that fails verification leaves no trace on disk. @throws NavCoreException.Verification if the signature or any layer hash does not verify.
  • public suspend fun install(snpkg: File, cancel: CancelToken): InstallOutcome: install with a cancellation handle. The core polls cancel between archive entries, before verification and before promotion; a tripped token (or a cancelled calling coroutine) yields InstallOutcome.Cancelled with staging removed and nothing installed.
  • public suspend fun installDirectory(packageDir: File): TerritoryInfo: Install an unpacked package directory (same verification rules).
  • public suspend fun installDirectory(packageDir: File, cancel: CancelToken): InstallOutcome: installDirectory with a cancellation handle; see install.
  • public suspend fun installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken()): ChannelInstallOutcome: Install territoryId from its channel: the first-install counterpart of applyUpdate. indexJson / indexSigBase64 are the exact served bytes of the channel index and its detached signature; the channel's latest version is installed, fetching only the layers not in omit through fetcher. 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 (verified layers stay in the layer cache). A tripped cancel (or a cancelled calling coroutine) yields ChannelInstallOutcome.Cancelled with nothing installed. @throws NavCoreException.Verification if a signature or hash does not verify, including a region- id on a store without a region key.
  • public suspend fun sync(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken()): ChannelSync: Bring territoryId to the channel's latest version, whichever way that takes: a first install from the channel when it is not installed, a signed differential update when an older version is, nothing when it is already current. Updates go through checkForUpdate / applyUpdate, so a channel can never move an installed territory backwards.
  • public suspend fun sync(territoryId: String, source: ChannelSource, apiKey: String? = null, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken(), onBytes: ((Long) -> Unit)? = null): ChannelSync: sync over HTTPS: fetch the signed index from source and every layer relative to it with an HttpChannelFetcher. cancel also stops a transfer in progress.
  • public suspend fun installCustomRegion(territoryId: String, indexUrl: String, indexSigUrl: String, apiKey: String? = null, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken(), onBytes: ((Long) -> Unit)? = null): ChannelSync: Install, or update, a custom region from the territory_id, index_url and index_sig_url of a POST /v1/jobs/territory result. A re-cut of the same area after the country is republished is the same id at a newer version, so calling this again is the update. @throws IllegalStateException if this store has no regionKeyHex. @throws IllegalArgumentException if territoryId is not a region- id or indexUrl is not an index.json URL.
  • public suspend fun verify(territoryId: String): 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 NavCoreException.Verification when the install must be repaired or reinstalled.
  • public suspend fun setActive(territoryId: String): Unit: Mark territoryId active; persisted atomically by the core.
  • public suspend fun active(): String?: The active territory id, if one is set and still installed.
  • public suspend fun activeTerritory(): TerritoryInfo?: The active territory's full info, if any.
  • public suspend fun layerPath(territoryId: String, kind: MapLayerKind): File: Absolute path of one layer of an installed territory, e.g. MapLayerKind.ValhallaTiles for the on-device router, MapLayerKind.Pmtiles for MapLibre.
  • public suspend fun territoryStyle(territoryId: String, theme: StyleTheme = StyleTheme.LIGHT): String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK's buildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via a pmtiles://<absolute path> URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly.
  • public suspend fun openSearch(territoryId: String): 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 across queries (calls are synchronous and disk-bound; keep them off the main thread): kotlin val search = store.openSearch("uk") val places = search.search("watford gap", near = null, limit = 10u)
  • public suspend fun remove(territoryId: String): Unit: Remove an installed territory (clears the active marker if needed).
  • public suspend fun planUpdate(newManifestJson: String): UpdatePlan: Plan a differential update against a newly served (signed) manifest JSON: which layers must be downloaded, and how many bytes.
  • public suspend fun checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher): AvailableUpdate?: Check the signed update channel for a newer version of an installed territory. Fail-closed: the channel index signature is verified before anything else, fetcher is never invoked for a channel that does not verify against this store's pinned key. @param indexJson the exact bytes served as index.json. @param indexSigBase64 the content of index.json.sig. @param fetcher the app's download transport (OkHttp, an air-gapped mirror, …), the core decides what to fetch and re-verifies all content itself. @return the available update, or null when already on the channel's latest version. @throws NavCoreException.Verification if the index or remote manifest signature does not verify.
  • public suspend fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher): UpdateResult: Apply a differential update: unchanged layers are hard-linked from the current install, only changed layers are fetched through fetcher, the staged package is fully re-verified, and the swap is atomic. Any failure, transport, hash mismatch, bad signature, leaves the installed territory untouched; the active flag survives.
  • public suspend fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken): UpdateOutcome: applyUpdate with a cancellation handle. The core polls cancel before every layer download, between archive entries while unpacking, before each hash pass and before promotion; a tripped token (or a cancelled calling coroutine) yields UpdateOutcome.Cancelled. The installed version is untouched and staging removed; layers already fetched and verified stay in the resumable cache, so a later attempt with the same manifest re-fetches only what is missing. The token cannot interrupt fetcher while it is inside a transfer: give the fetcher the same token and have it poll isCancelled() between chunks (or abort its request). Whatever the fetcher then throws, a tripped token reports UpdateOutcome.Cancelled rather than a transport error.
  • override fun close()

Example

kotlin
import ai.mapmap.territory.ChannelSource
import ai.mapmap.territory.TerritoryKeys
import ai.mapmap.territory.TerritoryStore
import java.io.File

suspend fun installUk(filesDir: File) {
    TerritoryStore(
        rootDir = File(filesDir, "territories"),
        verifyingKeyHex = TerritoryKeys.HOSTED_FACTORY_KEY_HEX,
        regionKeyHex = TerritoryKeys.HOSTED_REGION_KEY_HEX,
    ).use { store ->
        // First install or update, whichever is needed, from the hosted channel.
        val result = store.sync("uk", ChannelSource.gateway(), apiKey = "snk_…")
        store.setActive("uk")
        println(result)
    }
}

TtsStartup

Class · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public class TtsStartup<T>(private val languageTag: String?)

Pure init-order state machine for the asynchronous TextToSpeech engine, unit-testable on any JVM, like VoiceProsody.

The platform silently drops setLanguage calls made before the engine has finished initialising, so the language is applied in the SUCCESS callback, and before any prompt deferred during startup is flushed, so the first prompt already speaks in the configured voice.

PropertyTypeDefaultDescription
var readyBooleanfalseWhether the engine reported TextToSpeech.SUCCESS yet.

Initialisers and methods

  • public fun defer(announcement: T): Boolean: Defer announcement until init completes. Returns true when it was deferred (engine not ready, the latest prompt wins); false when the engine is ready and the caller should speak it now.
  • public fun onInitSuccess(): InitActions<T>: Handle the engine's SUCCESS callback. Idempotent per prompt.

Nested: TtsStartup.InitActions.

Example

kotlin
import ai.mapmap.nav.TtsStartup

// The start-up queue VoiceGuidance uses while TextToSpeech initialises: the latest prompt wins.
val startup = TtsStartup<String>(languageTag = "en-GB")
fun announce(text: String) {
    if (!startup.defer(text)) println("speak now: $text")
}
fun onTtsReady() {
    val actions = startup.onInitSuccess()
    actions.flush?.let { println("speak deferred: $it") }
}

TtsStartup.InitActions

Class · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public data class InitActions<T>(val languageToSet: String?, val flush: T?)

What to do on init SUCCESS, in order: set the language, then flush.

PropertyTypeDefaultDescription
val languageToSetString?
val flushT?

ValhallaMobileRouter

Class · ai/mapmap/routing/ValhallaMobileRouter.kt

kotlin
public class ValhallaMobileRouter(configPath: String) : OfflineRouter, AutoCloseable

OfflineRouter backed by the on-device Valhalla engine (ai.mapmap:valhalla-engine: Rallista/valhalla-mobile's wrapper, MIT, https://github.com/Rallista/valhalla-mobile, compiled against the Valhalla release and patch series the server builds tiles with; see tools/mobile-engine/engine.pin).

valhalla-mobile's actor exposes exactly the route(requestJson) -> responseJson shape the Rust core's LocalRouter callback expects; the call crosses into it through ValhallaActorBridge (see that file for why the seam is Java).

The engine is a compileOnly dependency of the SDK: apps that use this class must declare ai.mapmap:valhalla-engine themselves (see android/README.md). Do not use io.github.rallista:valhalla-mobile instead: its releases carry a different Valhalla than the factory tiles (0.5.1 to 0.6.3: 3.6.3, which answers 171 "No suitable edges" on them). Routing is CPU-bound native work: call it through OfflineRouting.route, which hops off the main thread.

Holds one native engine for its lifetime; reuse one router across routes and close it when done.

@param configPath absolute path of a valhalla.json whose mjolnir.tile_dir points at the territory's Valhalla tile layer.

Initialisers and methods

  • override fun route(requestJson: String): String
  • override fun close(): Unit: Release the native engine. Routing after this throws.

Nested: ValhallaMobileRouter.Companion.

Example

kotlin
import ai.mapmap.MapMap
import ai.mapmap.routing.OfflineRouting
import ai.mapmap.routing.ValhallaMobileRouter
import ai.mapmap.territory.TerritoryStore
import uniffi.mapmap.CostingModel
import uniffi.mapmap.MapLayerKind
import uniffi.mapmap.RoutePoint
import java.io.File

// On-device routing over an installed territory's Valhalla tiles.
suspend fun routeOffline(store: TerritoryStore, cacheDir: File) {
    val tiles = store.layerPath("uk", MapLayerKind.ValhallaTiles)
    ValhallaMobileRouter.fromTileDir(tiles, scratchDir = cacheDir).use { router ->
        val route = OfflineRouting.route(
            router,
            listOf(RoutePoint(51.5072, -0.1276), RoutePoint(51.4545, -2.5879)),
            costing = CostingModel.TRUCK,
            adr = MapMap.defaultAdrProfile(),
        )
        println(route)
    }
}

VoiceGuidance

Class · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public class VoiceGuidance(context: Context, language: String? = null, private val baseRate: Float = 1.0f) : AutoCloseable

Spoken turn-by-turn guidance over the platform TextToSpeech engine (offline-capable, no network required with a device voice installed).

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

kotlin val voice = VoiceGuidance(context) engine.navigate(provider) .onEach { voice.handle(it.update) } .collect { render(it) } // … voice.close()

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 flush the queue. 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). Audio focus is requested transiently with ducking (AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) around each announcement, so music dims rather than stops.

PropertyTypeDefaultDescription
var isSpeakingBooleanfalseWhether an utterance is currently being spoken or queued. Mirrors the transitions delivered to onSpeakingChanged. Guarded by synchronized(focusPolicy) like the underlying bookkeeping.
var onSpeakingChanged((Boolean) -> Unit)?nullInvoked on every speaking-state transition: true when the first utterance of a burst is handed to the engine, false once the last outstanding one ends (done, error, stop, mute or close). End transitions arrive on the TTS engine's callback thread, hop to the main thread before touching UI.
var mutedBooleanfalseWhether announcements are muted. Toggle freely mid-drive.
var volumeFloat1.0fAnnouncement volume, 0.0–1.0 (applied to speech and earcons).

Initialisers and methods

  • public fun handle(update: GuidanceUpdate): Consume one guidance update. Cheap; call it for every emission of NavigationEngine.navigate.
  • public fun handle(state: NavigationState): Unit: Convenience overload for NavigationEngine.navigate emissions.
  • override fun close(): Release the TTS engine, earcon player and audio focus.

Example

kotlin
import ai.mapmap.nav.VoiceGuidance
import android.content.Context

fun voice(context: Context): VoiceGuidance =
    VoiceGuidance(context, language = "en-GB").apply {
        volume = 0.8f
        onSpeakingChanged = { speaking -> println("speaking: $speaking") }
    }
// For every NavigationState from NavigationEngine.navigate: voice.handle(state). Close it when done.

VoiceProsody.Prosody

Class · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public data class Prosody(val rate: Float, val pitch: Float, val interrupt: Boolean)

Speech parameters for one severity level.

PropertyTypeDefaultDescription
val rateFloat
val pitchFloat
val interruptBoolean

Enums (ai.mapmap)

ProbeUploadOutcome

ProbeUploadOutcome

Enum · ai/mapmap/nav/ProbeContribution.kt

kotlin
public enum class ProbeUploadOutcome

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

CaseDescription
ACCEPTED202, accepted and stored.
REFUSED403, the key is not opted in; dropped, not retried.
NOT_ENABLED501, server collection is not enabled (SN_PROBE_DIR unset); dropped.
REJECTED400 or any other 4xx, malformed/unacceptable; dropped, not retried.
GAVE_UPIO error or 5xx after exhausting retries; given up on.

Interfaces (ai.mapmap)

ChannelSync, LocationProvider, OfflineRouter, ProbeUploader

ChannelSync

Interface · ai/mapmap/territory/TerritoryStore.kt

kotlin
public sealed interface ChannelSync

What TerritoryStore.sync did.

Nested: ChannelSync.Installed, ChannelSync.Updated, ChannelSync.UpToDate, ChannelSync.Cancelled.

LocationProvider

Interface · ai/mapmap/nav/LocationProvider.kt

kotlin
public interface LocationProvider

A source of location fixes for NavigationEngine.

Implementations: AndroidLocationProvider (the platform's fused provider) for live navigation, ReplayLocationProvider (a .drive.jsonl corpus) for QA and demos. Any cold Flow of samples in ascending timestamp order qualifies.

PropertyTypeDefaultDescription
val locationsFlow<LocationSample>The stream of fixes. Collected once per navigation session.

OfflineRouter

Interface · ai/mapmap/routing/OfflineRouter.kt

kotlin
public interface OfflineRouter : LocalRouter

An on-device routing engine.

This is the Rust core's LocalRouter callback interface with a Kotlin 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; tests inject fakes that return canned responses.

ProbeUploader

Interface · ai/mapmap/nav/ProbeContribution.kt

kotlin
public interface ProbeUploader

Where a completed probe batch goes. Called off the navigation flow's hot path: enqueue must be non-blocking and must never throw.

Initialisers and methods

  • public fun enqueue(body: String): Hand one probe body, the JSON string from uniffi.mapmap.ProbeCollector.finishJson, off to be POSTed to /v1/probe. Fire-and-forget.

Objects (ai.mapmap)

AdrCompliance, AndroidLocationProvider.Companion, ChannelSource.Companion, ChannelSync.Cancelled, DriveCorpus.Companion, GuidanceDisplay, MapMap, OfflineRouting, ReplayLocationProvider.Companion, TerritoryKeys, ValhallaConfigWriter, ValhallaMobileRouter.Companion, VoiceProsody

AdrCompliance

Object · ai/mapmap/adr/AdrCompliance.kt

kotlin
public object AdrCompliance

On-device ADR 8.6.4 dangerous-goods enforcement.

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

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

Initialisers and methods

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

AndroidLocationProvider.Companion

Object · ai/mapmap/nav/AndroidLocationProvider.kt

kotlin
public companion object

Initialisers and methods

  • public fun Location.toSample(): LocationSample: Map a platform Location onto the SDK's LocationSample.

ChannelSource.Companion

Object · ai/mapmap/territory/ChannelSource.kt

kotlin
public companion object

No trailing slash; layer paths are appended after a /.

PropertyTypeDefaultDescription
val DEFAULT_GATEWAYString"https://api.mapmap.ai"The hosted gateway.

Initialisers and methods

  • public fun gateway(baseUrl: String = DEFAULT_GATEWAY): ChannelSource: A gateway's country channel: GET /territories (the signed index) and GET /territories/index.sig.
  • public fun customRegion(territoryId: String, indexUrl: String, indexSigUrl: String): ChannelSource: A custom region's own one-territory channel, from the index_url / index_sig_url of a POST /v1/jobs/territory result. The gateway serves the index at <base>/v1/territories/<id>/index.json and the layers under <base>/territories/<id>/..., so the layer base is <base>. Any other .../index.json (a mirror of the region directory, laid out as SN_REGION_DIR/<id>/) resolves layers next to the index. @throws IllegalArgumentException if territoryId is not a custom-region id or indexUrl does not end in index.json.
  • public fun isCustomRegionId(territoryId: String): Boolean: Whether territoryId has the shape the gateway gives custom regions.

ChannelSync.Cancelled

Object · ai/mapmap/territory/TerritoryStore.kt

kotlin
public data object Cancelled : ChannelSync

The CancelToken was tripped; nothing changed on disk.

DriveCorpus.Companion

Object · ai/mapmap/replay/DriveCorpus.kt

kotlin
public companion object
PropertyTypeDefaultDescription
val FORMAT_VERSIONInt1The corpus format version this parser accepts.

Initialisers and methods

  • public fun parse(jsonl: String): DriveCorpus: Parse and validate a corpus from JSON-lines text. @throws CorpusFormatException describing the first violation, with its 1-based line number where applicable.

GuidanceDisplay

Object · ai/mapmap/nav/NavigationState.kt

kotlin
public object GuidanceDisplay

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

Initialisers and methods

  • public fun instruction(update: GuidanceUpdate): String?: The instruction to show for the current update, if any.
  • public fun severity(update: GuidanceUpdate): InstructionSeverity: How urgently the update should be surfaced (see the core's InstructionSeverity for the derivation). Off-route is a InstructionSeverity.WARNING, the driver has left the route and a recalculation is due; arrival is routine.
  • public fun 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 fun summarise(update: GuidanceUpdate): String: One-line status suitable for a debug HUD or notification.

MapMap

Object · ai/mapmap/MapMap.kt

kotlin
public object MapMap

Entry point for the MapMap Android SDK.

The SDK is a thin, idiomatic Kotlin layer over the Rust navigation core (sn-nav-core, shipped as libsn_nav_core.so). The raw UniFFI bindings live in uniffi.mapmap (and uniffi.ferrostar, which is linked into the same native library); everything under ai.mapmap is the supported surface:

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

Initialisers and methods

  • public fun ensureLoaded(): Eagerly load the native core and verify the bindings match it. Calling this is optional, the first native call loads the library lazily, but doing it at app start surfaces packaging problems (missing ABI, mismatched binding checksums) as an immediate UnsatisfiedLinkError instead of a mid-drive crash.
  • public fun defaultGuidanceConfig(): GuidanceConfig: A GuidanceConfig with the core's documented defaults.
  • public fun defaultAdrProfile(): AdrProfile: An AdrProfile with the core's documented defaults: EU maximum authorised dimensions (Council Directive 96/53/EC), no dangerous goods.

OfflineRouting

Object · ai/mapmap/routing/OfflineRouting.kt

kotlin
public object 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 ai.mapmap.nav.NavigationEngine.

Initialisers and methods

  • public fun requireCompatibleCosting(costing: CostingModel, adr: AdrProfile?): ADR profiles ride on Valhalla truck costing options; requesting any other costing model with an ADR profile is a contract violation the Rust core rejects. Checked here too so the failure is a fast, clearly-attributed IllegalArgumentException rather than a routing error after the FFI hop.
  • public suspend fun route(router: LocalRouter, waypoints: List<RoutePoint>, costing: CostingModel = CostingModel.AUTO, adr: AdrProfile? = null, dispatcher: CoroutineDispatcher = Dispatchers.Default): RouteResult: Compute a route on-device. @param router the on-device engine, usually a ValhallaMobileRouter. @param waypoints at least two RoutePoints, in visit order. @param costing the Valhalla costing model; must be CostingModel.TRUCK when adr is supplied. @param 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 NavCoreException.Routing when the engine returns a Valhalla error body (e.g. no route, no tiles for the area).
  • public fun buildRequest(waypoints: List<RoutePoint>, costing: CostingModel = CostingModel.AUTO, adr: AdrProfile? = null): String: Build the raw Valhalla request JSON without executing it, for callers that drive the engine themselves or log requests for audit.
  • public fun parseResponse(responseJson: String): RouteResult: Parse a raw engine response into a RouteResult.

ReplayLocationProvider.Companion

Object · ai/mapmap/nav/ReplayLocationProvider.kt

kotlin
public companion object

Initialisers and methods

  • public fun DriveFix.toSample(epochStartMs: Long): LocationSample: Map one corpus fix to a LocationSample rebased on epochStartMs.

TerritoryKeys

Object · ai/mapmap/territory/TerritoryKeys.kt

kotlin
public object TerritoryKeys

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

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

PropertyTypeDefaultDescription
val HOSTED_FACTORY_KEY_HEXString"c2230696626a1ecbc61cf9ac141eabea5a3a1a15dab70d2acc110bec79108bcf"The factory key: verifies every country package on the hosted channel (https://api.mapmap.ai/territories). Also published at mapmap.ai/docs/territories.
val HOSTED_REGION_KEY_HEXString"6f60f17bc31be2f7696cb957b2188416741e09cb3e7bdec2719fe553213be107"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(regionKeyHex = ...).

ValhallaConfigWriter

Object · ai/mapmap/routing/ValhallaConfigWriter.kt

kotlin
public object ValhallaConfigWriter

Writes the valhalla.json the on-device Valhalla actor 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 valhalla-defaults.json next to this class, with the tile source and a mobile-sized cache set on top. The actor 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 routing a custom region on a device, CustomRegionDeviceTest). The iOS writer bundles the same file.

PropertyTypeDefaultDescription
val DEFAULT_MAX_CACHE_BYTESLong268_435_456LMobile default for mjolnir.max_cache_size (bytes).

Initialisers and methods

  • public fun configJson(tileDir: File, maxCacheBytes: Long = DEFAULT_MAX_CACHE_BYTES): String: Render the config document for a routing-tile directory (the territory's uniffi.mapmap.MapLayerKind.ValhallaTiles layer).

ValhallaMobileRouter.Companion

Object · ai/mapmap/routing/ValhallaMobileRouter.kt

kotlin
public companion object

Initialisers and methods

  • public fun fromConfig(configFile: File): ValhallaMobileRouter: Create a router from an existing valhalla.json config file.
  • public fun fromTileDir(tileDir: File, scratchDir: File): ValhallaMobileRouter: Create a router for a territory's Valhalla tile directory, writing a config file under scratchDir (e.g. context.cacheDir). kotlin val tiles = store.layerPath(id, MapLayerKind.ValhallaTiles) val router = ValhallaMobileRouter.fromTileDir(tiles, context.cacheDir)

VoiceProsody

Object · ai/mapmap/nav/VoiceGuidance.kt

kotlin
public object VoiceProsody

Prosody and earcon policy per InstructionSeverity, pure and unit-testable on any JVM (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).

Initialisers and methods

  • public fun prosody(severity: InstructionSeverity, baseRate: Float = 1.0f): Prosody: Prosody for severity at baseRate (default 1.0).
  • public fun earconRes(severity: InstructionSeverity): Int?: The earcon raw resource for severity, or null when the severity plays none by default (INFO stays silent so a chime does not precede every routine manoeuvre). Assets are generated by scripts/generate-earcons.py.

Nested: VoiceProsody.Prosody.

Functions (ai.mapmap)

Flow<NavigationState>.contributingProbe

Flow<NavigationState>.contributingProbe

Function · ai/mapmap/nav/ProbeContribution.kt

kotlin
public fun Flow<NavigationState>.contributingProbe(config: ProbeConfig, uploader: ProbeUploader, routeRef: String? = null, territory: String? = null, vehicleClass: String? = null, now: () -> Long = System::currentTimeMillis): Flow<NavigationState>

Accumulates an aggregate probe batch from a navigation stream and uploads it once the trip ends. A transparent pass-through when config is disabled (the shipped default): no collector is constructed and nothing is uploaded, so leaving collection off costs nothing.

Wire it right onto the guidance stream: engine.navigate(provider) .contributingProbe( ProbeConfig(enabled = consentGranted), HttpProbeUploader("https://api.mapmap.ai", apiKey), routeRef = servedRouteToken, territory = "uk", vehicleClass = "truck_40t", ) .collect { render(it) }

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 is architecturally incapable of emitting a trajectory, and the first/last stretch of every trip is discarded on-device.

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

uniffi.mapmap

Classes (uniffi.mapmap)

AdrDecision, AdrDecision.Blocked, AdrProfile, AvailableUpdate, BannerLine, CancelToken, ChangedLayer, ChannelInstallOutcome, ChannelInstallOutcome.Installed, ChannelInstallResult, FasterRouteCandidate, FasterRouteConfig, FasterRouteRecommendation, FetchException, FetchException.Transport, GuidanceConfig, GuidanceSession, GuidanceUpdate, GuidanceUpdate.Navigating, GuidanceUpdate.OffRoute, InstallOutcome, InstallOutcome.Installed, LaneGuidance, LayerFetcherImpl, LocalRouterImpl, MapLayerKind, MapLayerKind.Extra, NavCoreException, NavCoreException.Guidance, NavCoreException.InvalidArgument, NavCoreException.LayerNotInstalled, NavCoreException.Routing, NavCoreException.Search, NavCoreException.Territory, NavCoreException.Verification, OdRecord, Place, ProbeBatch, ProbeCollector, ProbeConfig, ProbeEvent, ProbeEvent.EtaOutcome, ProbeEvent.OffRoute, RerouteAnchor, RerouteConfig, RerouteDecision, RerouteReason, RerouteReason.FasterRoute, RerouteReason.OffRoute, RerouteState, RerouteState.OffRouteSuspected, RerouteWaypoint, RouteManeuver, RoutePoint, RouteResult, RouteSummary, SegmentAggregate, SnappedFix, SpeedLimit, SpeedLimit.Known, SpokenPrompt, TerritoryInfo, TerritoryManager, TerritorySearch, UpdateOutcome, UpdateOutcome.Applied, UpdatePlan, UpdateResult, VisualBanner

AdrDecision

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class AdrDecision

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

Nested: AdrDecision.Allowed, AdrDecision.Blocked.

AdrDecision.Blocked

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Blocked(val reason: String) : AdrDecision()

Passage is forbidden.

PropertyTypeDefaultDescription
val reasonString

AdrProfile

Class · uniffi/mapmap/mapmap.kt

kotlin
data class AdrProfile (var heightM: Double = 4.0, var widthM: Double = 2.55, var lengthM: Double = 16.5, var grossWeightT: Double = 40.0, var axleLoadT: Double? = null, var axleCount: UInt? = null, var hazmat: Boolean = false, var tunnelCode: AdrTunnelCode? = null)

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

PropertyTypeDefaultDescription
var heightMDouble4.0
var widthMDouble2.55
var lengthMDouble16.5
var grossWeightTDouble40.0
var axleLoadTDouble?null
var axleCountUInt?null
var hazmatBooleanfalse
var tunnelCodeAdrTunnelCode?null

AvailableUpdate

Class · uniffi/mapmap/mapmap.kt

kotlin
data class AvailableUpdate (var version: String, var changedLayers: List<ChangedLayer>, var installedBytes: ULong, var manifestJson: String, var manifestSig: String)

An update the channel offers for an installed territory.

PropertyTypeDefaultDescription
var versionString
var changedLayersList<ChangedLayer>
var installedBytesULong
var manifestJsonString
var manifestSigString

BannerLine

Class · uniffi/mapmap/mapmap.kt

kotlin
data class BannerLine (var text: String, var maneuverType: String?, var maneuverModifier: String?, var roundaboutExitDegrees: UShort?, var exitNumbers: List<String>, var lanes: List<LaneGuidance>)

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

PropertyTypeDefaultDescription
var textString
var maneuverTypeString?
var maneuverModifierString?
var roundaboutExitDegreesUShort?
var exitNumbersList<String>
var lanesList<LaneGuidance>

CancelToken

Class · uniffi/mapmap/mapmap.kt

kotlin
open class CancelToken: Disposable, AutoCloseable, CancelTokenInterface

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

  • constructor(): A fresh, uncancelled token.
  • override fun destroy()
  • override fun close()
  • override fun cancel(): Request cancellation. Idempotent and safe from any thread.
  • override fun isCancelled(): Boolean: Whether [Self::cancel] has been called.

ChangedLayer

Class · uniffi/mapmap/mapmap.kt

kotlin
data class ChangedLayer (var kind: String, var path: String, var bytes: ULong)

One layer that a territory update must download.

PropertyTypeDefaultDescription
var kindString
var pathString
var bytesULong

ChannelInstallOutcome

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class ChannelInstallOutcome

How a channel install ended.

Nested: ChannelInstallOutcome.Installed, ChannelInstallOutcome.Cancelled.

ChannelInstallOutcome.Installed

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Installed(val result: uniffi.mapmap.ChannelInstallResult) : ChannelInstallOutcome()

The package verified and was promoted.

PropertyTypeDefaultDescription
val resultuniffi.mapmap.ChannelInstallResult

ChannelInstallResult

Class · uniffi/mapmap/mapmap.kt

kotlin
data class ChannelInstallResult (var territory: TerritoryInfo, var layersFetched: UInt, var layersReused: UInt, var bytesDownloaded: ULong)

What [TerritoryManager::install_from_channel] did.

PropertyTypeDefaultDescription
var territoryTerritoryInfo
var layersFetchedUInt
var layersReusedUInt
var bytesDownloadedULong

FasterRouteCandidate

Class · uniffi/mapmap/mapmap.kt

kotlin
data class FasterRouteCandidate (var id: String?, var durationS: Double)

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

PropertyTypeDefaultDescription
var idString?
var durationSDouble

FasterRouteConfig

Class · uniffi/mapmap/mapmap.kt

kotlin
data class FasterRouteConfig (var checkIntervalS: Double = 120.0, var minSavingS: UInt = 180u, var minSavingFrac: Double = 0.08, var dismissSuppressS: Double = 600.0, var maneuverBlackoutS: Double = 60.0, var enabled: Boolean = true)

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

PropertyTypeDefaultDescription
var checkIntervalSDouble120.0
var minSavingSUInt180u
var minSavingFracDouble0.08
var dismissSuppressSDouble600.0
var maneuverBlackoutSDouble60.0
var enabledBooleantrue

FasterRouteRecommendation

Class · uniffi/mapmap/mapmap.kt

kotlin
data class FasterRouteRecommendation (var savesS: UInt, var candidateIdx: UInt)

A recommendation to switch to a faster candidate route.

PropertyTypeDefaultDescription
var savesSUInt
var candidateIdxUInt

FetchException

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class FetchException: Exception()

A transport failure thrown by a foreign LayerFetcher implementation.

Nested: FetchException.Transport, FetchException.ErrorHandler.

FetchException.Transport

Class · uniffi/mapmap/mapmap.kt

kotlin
class Transport(override val message: String) : FetchException()

The download failed (network, storage, cancelled, …).

PropertyTypeDefaultDescription
val messageString

GuidanceConfig

Class · uniffi/mapmap/mapmap.kt

kotlin
data class GuidanceConfig (var stepAdvanceDistanceM: UShort = 20u, var minimumHorizontalAccuracyM: UShort = 25u, var routeDeviationThresholdM: Double = 25.0, var snapCourseToRoute: Boolean = true, var waypointAdvanceRangeM: Double = 100.0)

Guidance behaviour configuration, flattened for FFI.

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

PropertyTypeDefaultDescription
var stepAdvanceDistanceMUShort20u
var minimumHorizontalAccuracyMUShort25u
var routeDeviationThresholdMDouble25.0
var snapCourseToRouteBooleantrue
var waypointAdvanceRangeMDouble100.0

GuidanceSession

Class · uniffi/mapmap/mapmap.kt

kotlin
open class GuidanceSession: Disposable, AutoCloseable, GuidanceSessionInterface

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

  • constructor(routeResponseJson: String, config: GuidanceConfig): Create a session from a Valhalla route response JSON (as returned by route_offline in valhalla_response_json).
  • override fun destroy()
  • override fun close()
  • @Throws(NavCoreException::class) override fun advanceToNextStep(): GuidanceUpdate: Manually advance to the next step (e.g. in a tunnel with no GNSS).
  • override fun totalSteps(): UInt: Number of steps in the route, including the arrival step.
  • @Throws(NavCoreException::class) override fun updateLocation(lat: Double, lon: Double, timestampMs: Long, speedMps: Double?, courseDeg: Double?, horizontalAccuracyM: Double?): GuidanceUpdate: Feed a location fix; returns the updated guidance state. horizontal_accuracy_m defaults to 0.0 (trusted exactly) when absent; pass the platform's reported accuracy when available so step advance and deviation gating behave correctly.

GuidanceUpdate

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class GuidanceUpdate

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.

Nested: GuidanceUpdate.Navigating, GuidanceUpdate.Arrived, GuidanceUpdate.OffRoute.

GuidanceUpdate.Navigating

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Navigating(val stepIndex: UInt, val distanceToNextManeuverM: Double, val distanceRemainingM: Double, val durationRemainingS: Double, val currentInstruction: String, val deviationM: Double?, val visual: uniffi.mapmap.VisualBanner?, val spoken: uniffi.mapmap.SpokenPrompt?, val snapped: uniffi.mapmap.SnappedFix?, val severity: uniffi.mapmap.InstructionSeverity, val speedLimit: uniffi.mapmap.SpeedLimit?) : GuidanceUpdate()

Actively navigating.

PropertyTypeDefaultDescription
val stepIndexUInt
val distanceToNextManeuverMDouble
val distanceRemainingMDouble
val durationRemainingSDouble
val currentInstructionString
val deviationMDouble?
val visualuniffi.mapmap.VisualBanner?
val spokenuniffi.mapmap.SpokenPrompt?
val snappeduniffi.mapmap.SnappedFix?
val severityuniffi.mapmap.InstructionSeverity
val speedLimituniffi.mapmap.SpeedLimit?

GuidanceUpdate.OffRoute

Class · uniffi/mapmap/mapmap.kt

kotlin
data class OffRoute(val deviationM: Double) : GuidanceUpdate()

The user has left the route entirely (beyond the configured deviation threshold from every remaining step). The platform layer should recalculate.

PropertyTypeDefaultDescription
val deviationMDouble

InstallOutcome

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class InstallOutcome

How a cancellable install ended.

Nested: InstallOutcome.Installed, InstallOutcome.Cancelled.

InstallOutcome.Installed

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Installed(val territory: uniffi.mapmap.TerritoryInfo) : InstallOutcome()

The package verified and was promoted.

PropertyTypeDefaultDescription
val territoryuniffi.mapmap.TerritoryInfo

LaneGuidance

Class · uniffi/mapmap/mapmap.kt

kotlin
data class LaneGuidance (var directions: List<String>, var active: Boolean, var activeDirection: String?)

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

PropertyTypeDefaultDescription
var directionsList<String>
var activeBoolean
var activeDirectionString?

LayerFetcherImpl

Class · uniffi/mapmap/mapmap.kt

kotlin
open class LayerFetcherImpl: Disposable, AutoCloseable, LayerFetcher

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

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

LocalRouterImpl

Class · uniffi/mapmap/mapmap.kt

kotlin
open class LocalRouterImpl: Disposable, AutoCloseable, LocalRouter

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

  • override fun destroy()
  • override fun close()
  • override fun 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).

MapLayerKind

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class MapLayerKind

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

Nested: MapLayerKind.ValhallaTiles, MapLayerKind.Pmtiles, MapLayerKind.GeocodeIndex, MapLayerKind.PoiSidecar, MapLayerKind.Extra.

MapLayerKind.Extra

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Extra(val name: String) : MapLayerKind()

Any other layer kind, by its manifest string.

PropertyTypeDefaultDescription
val nameString

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class NavCoreException: Exception()

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.

Nested: NavCoreException.Territory, NavCoreException.Verification, NavCoreException.Routing, NavCoreException.Guidance, NavCoreException.InvalidArgument, NavCoreException.Search, NavCoreException.LayerNotInstalled, NavCoreException.ErrorHandler.

Class · uniffi/mapmap/mapmap.kt

kotlin
class Guidance(override val message: String) : NavCoreException()

Guidance session failure.

PropertyTypeDefaultDescription
val messageString

Class · uniffi/mapmap/mapmap.kt

kotlin
class InvalidArgument(override val message: String) : NavCoreException()

A caller-supplied argument was invalid.

PropertyTypeDefaultDescription
val messageString

Class · uniffi/mapmap/mapmap.kt

kotlin
class LayerNotInstalled(val territoryId: String, val kind: String, val detail: String) : NavCoreException()

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.

PropertyTypeDefaultDescription
val territoryIdString
val kindString
val detailString
val messageHuman-readable description.

Class · uniffi/mapmap/mapmap.kt

kotlin
class Routing(override val message: String) : NavCoreException()

Route request building or response parsing failure (including Valhalla error bodies from the on-device engine).

PropertyTypeDefaultDescription
val messageString

Class · uniffi/mapmap/mapmap.kt

kotlin
class Search(override val message: String) : NavCoreException()

On-device geocode search failure (index missing, unreadable or of an unsupported schema version).

PropertyTypeDefaultDescription
val messageString

Class · uniffi/mapmap/mapmap.kt

kotlin
class Territory(override val message: String) : NavCoreException()

Territory storage or lifecycle failure.

PropertyTypeDefaultDescription
val messageString

Class · uniffi/mapmap/mapmap.kt

kotlin
class Verification(override val message: String) : NavCoreException()

A package failed cryptographic or integrity verification.

PropertyTypeDefaultDescription
val messageString

OdRecord

Class · uniffi/mapmap/mapmap.kt

kotlin
data class OdRecord (var originCell: String, var destCell: String, var departBucket: String)

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

PropertyTypeDefaultDescription
var originCellString
var destCellString
var departBucketString

Place

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Place (var id: String, var kind: PlaceKind, var name: String, var housenumber: String?, var street: String?, var locality: String?, var region: String?, var postcode: String?, var countryCode: String, var lat: Double, var lon: Double, var categories: List<String>, var importance: Float, var distanceM: Double?)

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

PropertyTypeDefaultDescription
var idString
var kindPlaceKind
var nameString
var housenumberString?
var streetString?
var localityString?
var regionString?
var postcodeString?
var countryCodeString
var latDouble
var lonDouble
var categoriesList<String>
var importanceFloat
var distanceMDouble?

ProbeBatch

Class · uniffi/mapmap/mapmap.kt

kotlin
data class ProbeBatch (var probeFormat: UInt, var territory: String?, var vehicleClass: String?, var routeRef: String?, var segments: List<SegmentAggregate>, var events: List<ProbeEvent>, var od: OdRecord?)

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

PropertyTypeDefaultDescription
var probeFormatUInt
var territoryString?
var vehicleClassString?
var routeRefString?
var segmentsList<SegmentAggregate>
var eventsList<ProbeEvent>
var odOdRecord?

ProbeCollector

Class · uniffi/mapmap/mapmap.kt

kotlin
open class ProbeCollector: Disposable, AutoCloseable, ProbeCollectorInterface

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

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

ProbeConfig

Class · uniffi/mapmap/mapmap.kt

kotlin
data class ProbeConfig (var enabled: Boolean = false, var tripEndSuppressionM: Double = 500.0, var minSegmentObservations: UInt = 1u, var timeBucketMinutes: UInt = 5u, var odCellPrecision: UByte = 5u, var collectOd: Boolean = true)

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

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

PropertyTypeDefaultDescription
var enabledBooleanfalse
var tripEndSuppressionMDouble500.0
var minSegmentObservationsUInt1u
var timeBucketMinutesUInt5u
var odCellPrecisionUByte5u
var collectOdBooleantrue

ProbeEvent

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class ProbeEvent

A coarse, time-bucketed event within a trip.

Nested: ProbeEvent.OffRoute, ProbeEvent.EtaOutcome.

ProbeEvent.EtaOutcome

Class · uniffi/mapmap/mapmap.kt

kotlin
data class EtaOutcome(val predictedS: Double, val actualS: Double, val routeLenKmBucket: String) : ProbeEvent()

The realised trip duration against the engine's first estimate. Feeds ETA-accuracy calibration; carries no location.

PropertyTypeDefaultDescription
val predictedSDouble
val actualSDouble
val routeLenKmBucketString

ProbeEvent.OffRoute

Class · uniffi/mapmap/mapmap.kt

kotlin
data class OffRoute(val todBucket: String, val deviationBandM: UInt) : ProbeEvent()

The vehicle left the route (a confirmed off-route condition from guidance). Carries only the time bucket and a coarse deviation band.

PropertyTypeDefaultDescription
val todBucketString
val deviationBandMUInt

RerouteAnchor

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RerouteAnchor (var lat: Double, var lon: Double, var courseDeg: Double?)

The point and course a recalculated route should depart from.

PropertyTypeDefaultDescription
var latDouble
var lonDouble
var courseDegDouble?

RerouteConfig

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RerouteConfig (var minConsecutiveOffrouteFixes: UInt = 3u, var minOffrouteDurationS: Double = 5.0, var minIntervalBetweenReroutesS: Double = 10.0, var enabled: Boolean = true)

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

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

PropertyTypeDefaultDescription
var minConsecutiveOffrouteFixesUInt3u
var minOffrouteDurationSDouble5.0
var minIntervalBetweenReroutesSDouble10.0
var enabledBooleantrue

RerouteDecision

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RerouteDecision (var reason: RerouteReason, var anchor: RerouteAnchor, var waypointsRemaining: List<RerouteWaypoint>)

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

PropertyTypeDefaultDescription
var reasonRerouteReason
var anchorRerouteAnchor
var waypointsRemainingList<RerouteWaypoint>

RerouteReason

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class RerouteReason

Why a reroute was requested.

Nested: RerouteReason.OffRoute, RerouteReason.FasterRoute.

RerouteReason.FasterRoute

Class · uniffi/mapmap/mapmap.kt

kotlin
data class FasterRoute(val savesS: UInt) : RerouteReason()

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.

PropertyTypeDefaultDescription
val savesSUInt

RerouteReason.OffRoute

Class · uniffi/mapmap/mapmap.kt

kotlin
data class OffRoute(val deviationM: Double) : RerouteReason()

The vehicle left the route line; deviation_m is the distance from the route at the confirming fix.

PropertyTypeDefaultDescription
val deviationMDouble

RerouteState

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class RerouteState

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

Nested: RerouteState.Monitoring, RerouteState.OffRouteSuspected, RerouteState.RerouteNeeded, RerouteState.CoolingDown.

RerouteState.OffRouteSuspected

Class · uniffi/mapmap/mapmap.kt

kotlin
data class OffRouteSuspected(val count: UInt) : RerouteState()

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.

PropertyTypeDefaultDescription
val countUInt

RerouteWaypoint

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RerouteWaypoint (var lat: Double, var lon: Double, var isBreak: Boolean)

One onward waypoint of the active route.

PropertyTypeDefaultDescription
var latDouble
var lonDouble
var isBreakBoolean

RouteManeuver

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RouteManeuver (var instruction: String, var maneuverType: UInt, var verbalPreTransitionInstruction: String?, var verbalPostTransitionInstruction: String?, var streetNames: List<String>, var distanceM: Double, var durationS: Double, var beginShapeIndex: UInt, var endShapeIndex: UInt, var roundaboutExitCount: UInt?)

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

PropertyTypeDefaultDescription
var instructionString
var maneuverTypeUInt
var verbalPreTransitionInstructionString?
var verbalPostTransitionInstructionString?
var streetNamesList<String>
var distanceMDouble
var durationSDouble
var beginShapeIndexUInt
var endShapeIndexUInt
var roundaboutExitCountUInt?

RoutePoint

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RoutePoint (var lat: Double, var lon: Double)

A route waypoint.

PropertyTypeDefaultDescription
var latDouble
var lonDouble

RouteResult

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RouteResult (var summary: RouteSummary, var geometry: List<RoutePoint> = listOf(), var maneuvers: List<RouteManeuver> = listOf(), var valhallaResponseJson: String, var osrmResponseJson: String)

Result of an offline route computation.

PropertyTypeDefaultDescription
var summaryRouteSummary
var geometryList<RoutePoint>listOf()
var maneuversList<RouteManeuver>listOf()
var valhallaResponseJsonString
var osrmResponseJsonString

RouteSummary

Class · uniffi/mapmap/mapmap.kt

kotlin
data class RouteSummary (var distanceM: Double, var durationS: Double, var hasToll: Boolean, var hasHighway: Boolean, var hasFerry: Boolean)

SI summary of a parsed route.

PropertyTypeDefaultDescription
var distanceMDouble
var durationSDouble
var hasTollBoolean
var hasHighwayBoolean
var hasFerryBoolean

SegmentAggregate

Class · uniffi/mapmap/mapmap.kt

kotlin
data class SegmentAggregate (var stepIndex: UInt, var todBucket: String, var observations: UInt, var meanSpeedKmh: Double, var p85SpeedKmh: Double, var stoppedS: Double, var limitDeltaKmh: Double?)

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

PropertyTypeDefaultDescription
var stepIndexUInt
var todBucketString
var observationsUInt
var meanSpeedKmhDouble
var p85SpeedKmhDouble
var stoppedSDouble
var limitDeltaKmhDouble?

SnappedFix

Class · uniffi/mapmap/mapmap.kt

kotlin
data class SnappedFix (var lat: Double, var lon: Double, var courseDeg: Double?)

The route-snapped position for the current update.

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

PropertyTypeDefaultDescription
var latDouble
var lonDouble
var courseDegDouble?

SpeedLimit

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class SpeedLimit

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.

Nested: SpeedLimit.Known, SpeedLimit.Unlimited, SpeedLimit.Unknown.

SpeedLimit.Known

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Known(val kmh: Double) : SpeedLimit()

A known posted limit, normalised to kilometres per hour regardless of the unit the route expressed it in.

PropertyTypeDefaultDescription
val kmhDouble

SpokenPrompt

Class · uniffi/mapmap/mapmap.kt

kotlin
data class SpokenPrompt (var text: String, var ssml: String?, var triggerDistanceM: Double, var utteranceId: String)

The spoken prompt to synthesise for the upcoming maneuver.

PropertyTypeDefaultDescription
var textString
var ssmlString?
var triggerDistanceMDouble
var utteranceIdString

TerritoryInfo

Class · uniffi/mapmap/mapmap.kt

kotlin
data class TerritoryInfo (var territoryId: String, var displayName: String, var version: String, var dataTimestamp: String, var west: Double, var south: Double, var east: Double, var north: Double, var totalBytes: ULong, var installedBytes: ULong, var omittedKinds: List<MapLayerKind>, var path: String, var active: Boolean)

Summary of one installed territory.

PropertyTypeDefaultDescription
var territoryIdString
var displayNameString
var versionString
var dataTimestampString
var westDouble
var southDouble
var eastDouble
var northDouble
var totalBytesULong
var installedBytesULong
var omittedKindsList<MapLayerKind>
var pathString
var activeBoolean

TerritoryManager

Class · uniffi/mapmap/mapmap.kt

kotlin
open class TerritoryManager: Disposable, AutoCloseable, TerritoryManagerInterface

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

Initialisers and methods

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

Nested: TerritoryManager.Companion.

TerritorySearch

Class · uniffi/mapmap/mapmap.kt

kotlin
open class TerritorySearch: Disposable, AutoCloseable, TerritorySearchInterface

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

  • override fun destroy()
  • override fun close()
  • @Throws(NavCoreException::class) override fun reverse(lat: Double, lon: Double, limit: UInt): List<Place>: Reverse geocode: the nearest indexed places to a coordinate, nearest first.
  • @Throws(NavCoreException::class) override fun search(query: String, near: RoutePoint?, limit: UInt): List<Place>: Free-text search (addresses, streets, places, POIs, UK postcodes; prefix-tokenised, so it works for search-as-you-type). near biases ranking towards the given point and fills each result's distance_m; limit caps the number of hits.

UpdateOutcome

Class · uniffi/mapmap/mapmap.kt

kotlin
sealed class UpdateOutcome

How a cancellable update ended.

Nested: UpdateOutcome.Applied, UpdateOutcome.Cancelled.

UpdateOutcome.Applied

Class · uniffi/mapmap/mapmap.kt

kotlin
data class Applied(val result: uniffi.mapmap.UpdateResult) : UpdateOutcome()

The update verified and was swapped in.

PropertyTypeDefaultDescription
val resultuniffi.mapmap.UpdateResult

UpdatePlan

Class · uniffi/mapmap/mapmap.kt

kotlin
data class UpdatePlan (var changed: List<ChangedLayer>, var installedBytes: ULong)

A differential update plan.

PropertyTypeDefaultDescription
var changedList<ChangedLayer>
var installedBytesULong

UpdateResult

Class · uniffi/mapmap/mapmap.kt

kotlin
data class UpdateResult (var territory: TerritoryInfo, var previousVersion: String, var layersFetched: UInt, var layersReused: UInt, var bytesDownloaded: ULong)

What [TerritoryManager::apply_update] did.

PropertyTypeDefaultDescription
var territoryTerritoryInfo
var previousVersionString
var layersFetchedUInt
var layersReusedUInt
var bytesDownloadedULong

VisualBanner

Class · uniffi/mapmap/mapmap.kt

kotlin
data class VisualBanner (var primary: BannerLine, var secondary: BannerLine?, var sub: BannerLine?, var triggerDistanceM: Double, var drivingSide: String? = null, var roadRef: String? = null, var country: String? = null, var subdivision: String? = null, var roadClass: String? = null)

The visual banner to display for the upcoming maneuver.

PropertyTypeDefaultDescription
var primaryBannerLine
var secondaryBannerLine?
var subBannerLine?
var triggerDistanceMDouble
var drivingSideString?null
var roadRefString?null
var countryString?null
var subdivisionString?null
var roadClassString?null

Enums (uniffi.mapmap)

AdrTunnelCategory, AdrTunnelCode, CostingModel, InstructionSeverity, PlaceKind, StyleTheme

AdrTunnelCategory

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class AdrTunnelCategory

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

CaseDescription
ANo dangerous-goods restriction.
BRestriction for goods which may lead to a very large explosion.
C… or a large explosion or large toxic release.
D… or a large fire.
ERestriction for nearly all dangerous goods.

AdrTunnelCode

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class AdrTunnelCode

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

CaseDescription
NO_CODEADR (, ), passage permitted through all tunnels.
BCode B.
B1000CCode B1000C.
BDCode B/D.
BECode B/E.
CCode C.
C5000DCode C5000D.
CDCode C/D.
CECode C/E.
DCode D.
DECode D/E.
ECode E.

CostingModel

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class CostingModel

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

CaseDescription
AUTOStandard car costing.
TRUCKTruck costing (required when an ADR profile is supplied).
BUSBus costing.
MOTOR_SCOOTERMotor scooter costing.
MOTORCYCLEMotorcycle costing.
BICYCLEBicycle costing.
PEDESTRIANPedestrian costing.

InstructionSeverity

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class InstructionSeverity

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

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

Derivation (single source of truth for every SDK):

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

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

CaseDescription
INFOA normal manoeuvre announcement.
WARNINGApproaching a restriction (toll booth, ferry boarding/landing).
CRITICALA prohibition: ADR tunnel block or a gate across the carriageway.

PlaceKind

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class PlaceKind

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

CaseDescription
ADDRESSA single addressable building or unit (housenumber + street).
STREETA named street or road.
LOCALITYA town, city, village or suburb.
POIA point of interest (fuel station, truck stop, museum, …).
POSTCODEA postcode centroid (full or outward code).

StyleTheme

Enum · uniffi/mapmap/mapmap.kt

kotlin
enum class StyleTheme

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

CaseDescription
LIGHTThe light (day) style, also the package default.
DARKThe dark (night) style.

Interfaces (uniffi.mapmap)

CancelTokenInterface, GuidanceSessionInterface, LayerFetcher, LocalRouter, ProbeCollectorInterface, TerritoryManagerInterface, TerritorySearchInterface

CancelTokenInterface

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface CancelTokenInterface

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

  • fun cancel(): Request cancellation. Idempotent and safe from any thread.
  • fun isCancelled(): Boolean: Whether [Self::cancel] has been called.

GuidanceSessionInterface

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface GuidanceSessionInterface

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

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

LayerFetcher

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface LayerFetcher

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

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

LocalRouter

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface LocalRouter

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

  • fun 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).

ProbeCollectorInterface

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface ProbeCollectorInterface

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

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

TerritoryManagerInterface

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface TerritoryManagerInterface

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

Initialisers and methods

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

TerritorySearchInterface

Interface · uniffi/mapmap/mapmap.kt

kotlin
public interface TerritorySearchInterface

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

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

Objects (uniffi.mapmap)

AdrDecision.Allowed, ChannelInstallOutcome.Cancelled, FetchException.ErrorHandler, GuidanceUpdate.Arrived, InstallOutcome.Cancelled, MapLayerKind.GeocodeIndex, MapLayerKind.Pmtiles, MapLayerKind.PoiSidecar, MapLayerKind.ValhallaTiles, NavCoreException.ErrorHandler, RerouteState.CoolingDown, RerouteState.Monitoring, RerouteState.RerouteNeeded, SpeedLimit.Unknown, SpeedLimit.Unlimited, TerritoryManager.Companion, UpdateOutcome.Cancelled

AdrDecision.Allowed

Object · uniffi/mapmap/mapmap.kt

kotlin
object Allowed : AdrDecision()

Passage is permitted.

ChannelInstallOutcome.Cancelled

Object · uniffi/mapmap/mapmap.kt

kotlin
object Cancelled : ChannelInstallOutcome()

The CancelToken was tripped before promotion. Nothing was installed; verified layers stay parked for the next attempt.

FetchException.ErrorHandler

Object · uniffi/mapmap/mapmap.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<FetchException>

Human-readable description of the failure.

GuidanceUpdate.Arrived

Object · uniffi/mapmap/mapmap.kt

kotlin
object Arrived : GuidanceUpdate()

The user has arrived at the destination.

InstallOutcome.Cancelled

Object · uniffi/mapmap/mapmap.kt

kotlin
object Cancelled : InstallOutcome()

The CancelToken was tripped before promotion. Nothing was installed; staging was removed.

MapLayerKind.GeocodeIndex

Object · uniffi/mapmap/mapmap.kt

kotlin
object GeocodeIndex : MapLayerKind()

Tantivy geocoding index.

MapLayerKind.Pmtiles

Object · uniffi/mapmap/mapmap.kt

kotlin
object Pmtiles : MapLayerKind()

PMTiles render layer.

MapLayerKind.PoiSidecar

Object · uniffi/mapmap/mapmap.kt

kotlin
object PoiSidecar : MapLayerKind()

Proprietary POI sidecar database.

MapLayerKind.ValhallaTiles

Object · uniffi/mapmap/mapmap.kt

kotlin
object ValhallaTiles : MapLayerKind()

Valhalla routing tile tree.

Object · uniffi/mapmap/mapmap.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<NavCoreException>

RerouteState.CoolingDown

Object · uniffi/mapmap/mapmap.kt

kotlin
object CoolingDown : RerouteState()

Off route and confirmed again, but suppressed because a reroute fired within [RerouteConfig::min_interval_between_reroutes_s].

RerouteState.Monitoring

Object · uniffi/mapmap/mapmap.kt

kotlin
object Monitoring : RerouteState()

On route (or recovered): nothing to do.

RerouteState.RerouteNeeded

Object · uniffi/mapmap/mapmap.kt

kotlin
object RerouteNeeded : RerouteState()

A reroute is confirmed for this update; the accompanying RerouteDecision should be routed. Reported exactly once per confirmed departure.

SpeedLimit.Unknown

Object · uniffi/mapmap/mapmap.kt

kotlin
object Unknown : SpeedLimit()

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.

SpeedLimit.Unlimited

Object · uniffi/mapmap/mapmap.kt

kotlin
object Unlimited : SpeedLimit()

The road is de-restricted (Mapbox maxspeed none; OSM maxspeed=none, e.g. a German autobahn), show a "no limit" badge, do not warn.

TerritoryManager.Companion

Object · uniffi/mapmap/mapmap.kt

kotlin
companion object

Initialisers and methods

  • @Throws(NavCoreException::class) fun withRegionKey(rootDir: String, verifyingKeyHex: String, regionKeyHex: String): TerritoryManager: [Self::new], also trusting custom regions (region-… ids, cut by POST /v1/jobs/territory) signed by region_key_hex, the public half of the gateway's region signing key. The keys are partitioned by id: the region key verifies region- ids only and the factory key everything else. Pin both in the app; never read either from the network.

UpdateOutcome.Cancelled

Object · uniffi/mapmap/mapmap.kt

kotlin
object Cancelled : UpdateOutcome()

The CancelToken was tripped before promotion. The installed version is untouched; verified layers stay parked for a retry.

Functions (uniffi.mapmap)

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

buildOfflineRouteRequest

Function · uniffi/mapmap/mapmap.kt

kotlin
@Throws(NavCoreException::class) fun buildOfflineRouteRequest(locations: List<RoutePoint>, costing: CostingModel, adr: AdrProfile?): 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 · uniffi/mapmap/mapmap.kt

kotlin
fun 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 · uniffi/mapmap/mapmap.kt

kotlin
fun forbiddenCategories(profile: AdrProfile): List<AdrTunnelCategory>

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

parseRouteResult

Function · uniffi/mapmap/mapmap.kt

kotlin
@Throws(NavCoreException::class) fun parseRouteResult(responseJson: String): RouteResult

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

routeOffline

Function · uniffi/mapmap/mapmap.kt

kotlin
@Throws(NavCoreException::class) fun routeOffline(router: LocalRouter, locations: List<RoutePoint>, costing: CostingModel, adr: AdrProfile?): 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 · uniffi/mapmap/mapmap.kt

kotlin
@Throws(NavCoreException::class) fun styleForNavigation(styleJson: String, keepBuildings3d: Boolean = true): 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 · uniffi/mapmap/mapmap.kt

kotlin
@Throws(NavCoreException::class) fun styleWithBuildings3d(styleJson: String, enabled: Boolean): 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.

uniffi.ferrostar

Classes (uniffi.ferrostar)

AndAdvanceConditions, BoundingBox, Congestion, CourseOverGround, DeviationKind, DeviationKind.CompletelyOffRoute, DeviationKind.OffStepOnRoute, DistanceEntryAndExitCondition, DistanceEntryAndSnappedExitCondition, DistanceFromStepCondition, DistanceToEndOfStepCondition, GeographicCoordinate, Heading, Incident, InstantiationException, InstantiationException.OptionsJsonParseException, LaneInfo, LocationBias, LocationBias.Left, LocationBias.Random, LocationBias.Right, LocationSimulationState, ManualStepCondition, ModelException, ModelException.PolylineGenerationException, NavigationCacheImpl, NavigationCachingConfig, NavigationController, NavigationControllerConfig, NavigationObserverImpl, NavigationRecorder, NavigationRecordingEvent, NavigationRecordingEventData, NavigationRecordingEventData.RouteUpdate, NavigationRecordingEventData.StateUpdate, NavigationReplay, NavigationSession, NavigationSessionCache, NavigationSessionSnapshot, Navigator, NavState, OrAdvanceConditions, OsrmWaypointProperties, ParsingException, ParsingException.InvalidGeometry, ParsingException.InvalidRouteObject, ParsingException.InvalidStatusCode, ParsingException.MalformedAnnotations, ParsingException.UnknownParsingException, RecordingException, RecordingException.DeserializationException, RecordingException.RecordingNotEnabled, RecordingException.SerializationException, Route, RouteAdapter, RouteDeviation, RouteDeviation.Deviation, RouteDeviationDetectorImpl, RouteDeviationTracking, RouteDeviationTracking.Custom, RouteDeviationTracking.StaticThreshold, RouteRequest, RouteRequest.HttpGet, RouteRequest.HttpPost, RouteRequestGeneratorImpl, RouteResponseParserImpl, RouteStep, RoutingRequestGenerationException, RoutingRequestGenerationException.JsonException, RoutingRequestGenerationException.NotEnoughWaypoints, RoutingRequestGenerationException.UnknownRequestGenerationException, SerializableNavState, SerializableStepAdvanceCondition, SerializableStepAdvanceCondition.AndAdvanceConditions, SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit, SerializableStepAdvanceCondition.DistanceEntryExit, SerializableStepAdvanceCondition.DistanceFromStep, SerializableStepAdvanceCondition.DistanceToEndOfStep, SerializableStepAdvanceCondition.OrAdvanceConditions, SimulationException, SimulationException.NotEnoughPoints, SimulationException.PolylineException, Speed, SpokenInstruction, StepAdvanceCondition, StepAdvanceResult, TripProgress, TripState, TripState.Complete, TripState.Idle, TripState.Navigating, TripSummary, UserLocation, ValhallaLocationSearchFilter, ValhallaWaypointProperties, VisualInstruction, VisualInstructionContent, Waypoint, WaypointAdvanceMode, WaypointAdvanceMode.WaypointAlongAdvancingStep, WaypointAdvanceMode.WaypointWithinRange, WellKnownRouteProvider, WellKnownRouteProvider.GraphHopper, WellKnownRouteProvider.Valhalla

AndAdvanceConditions

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class AndAdvanceConditions: Disposable, AutoCloseable, AndAdvanceConditionsInterface

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

Initialisers and methods

  • override fun destroy()
  • override fun close()

BoundingBox

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class BoundingBox (var sw: GeographicCoordinate, var ne: GeographicCoordinate)

A geographic bounding box defined by its corners.

PropertyTypeDefaultDescription
var swGeographicCoordinate
var neGeographicCoordinate

Congestion

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Congestion (var value: UByte)

Details about congestion for an incident.

PropertyTypeDefaultDescription
var valueUByte

CourseOverGround

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class CourseOverGround (var degrees: UShort, var accuracy: UShort?)

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

PropertyTypeDefaultDescription
var degreesUShort
var accuracyUShort?

DeviationKind

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class DeviationKind

The kind of deviation from the expected route.

Nested: DeviationKind.OffStepOnRoute, DeviationKind.CompletelyOffRoute.

DeviationKind.CompletelyOffRoute

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class CompletelyOffRoute(val deviationFromRouteLine: Double) : DeviationKind()

The user is off the expected route entirely (not within threshold of any remaining step, neither the current one nor any future one).

PropertyTypeDefaultDescription
val deviationFromRouteLineDouble

DeviationKind.OffStepOnRoute

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class OffStepOnRoute(val deviationFromStepLine: Double) : DeviationKind()

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.

PropertyTypeDefaultDescription
val deviationFromStepLineDouble

DistanceEntryAndExitCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class DistanceEntryAndExitCondition: Disposable, AutoCloseable, DistanceEntryAndExitConditionInterface

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

Initialisers and methods

  • override fun destroy()
  • override fun close()

DistanceEntryAndSnappedExitCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class DistanceEntryAndSnappedExitCondition: Disposable, AutoCloseable, DistanceEntryAndSnappedExitConditionInterface

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.

Initialisers and methods

  • override fun destroy()
  • override fun close()

DistanceFromStepCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class DistanceFromStepCondition: Disposable, AutoCloseable, DistanceFromStepConditionInterface

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.

Initialisers and methods

  • override fun destroy()
  • override fun close()

DistanceToEndOfStepCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class DistanceToEndOfStepCondition: Disposable, AutoCloseable, DistanceToEndOfStepConditionInterface

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.

Initialisers and methods

  • override fun destroy()
  • override fun close()

GeographicCoordinate

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class GeographicCoordinate (var lat: Double, var lng: Double)

A geographic coordinate in WGS84.

PropertyTypeDefaultDescription
var latDouble
var lngDouble

Heading

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Heading (var trueHeading: UShort, var accuracy: UShort, var timestamp: java.time.Instant)

The heading of the user/device.

PropertyTypeDefaultDescription
var trueHeadingUShort
var accuracyUShort
var timestampjava.time.Instant

Incident

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Incident (var id: String, var incidentType: IncidentType, var description: String?, var longDescription: String?, var creationTime: UtcDateTime?, var startTime: UtcDateTime?, var endTime: UtcDateTime?, var impact: Impact?, var lanesBlocked: List<BlockedLane>, var congestion: Congestion?, var closed: Boolean?, var geometryIndexStart: ULong, var geometryIndexEnd: ULong?, var subType: String?, var subTypeDescription: String?, var iso31661Alpha2: String?, var iso31661Alpha3: String?, var affectedRoadNames: List<String>, var bbox: BoundingBox?)

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

PropertyTypeDefaultDescription
var idString
var incidentTypeIncidentType
var descriptionString?
var longDescriptionString?
var creationTimeUtcDateTime?
var startTimeUtcDateTime?
var endTimeUtcDateTime?
var impactImpact?
var lanesBlockedList<BlockedLane>
var congestionCongestion?
var closedBoolean?
var geometryIndexStartULong
var geometryIndexEndULong?
var subTypeString?
var subTypeDescriptionString?
var iso31661Alpha2String?
var iso31661Alpha3String?
var affectedRoadNamesList<String>
var bboxBoundingBox?

InstantiationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class InstantiationException: Exception()

Nested: InstantiationException.OptionsJsonParseException, InstantiationException.ErrorHandler.

InstantiationException.OptionsJsonParseException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class OptionsJsonParseException() : InstantiationException()
PropertyTypeDefaultDescription
val message

LaneInfo

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class LaneInfo (var active: Boolean, var directions: List<String>, var activeDirection: String?)

The content of a visual instruction.

PropertyTypeDefaultDescription
var activeBoolean
var directionsList<String>
var activeDirectionString?

LocationBias

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class LocationBias

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

Nested: LocationBias.Left, LocationBias.Right, LocationBias.Random, LocationBias.None.

LocationBias.Left

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Left(val v1: Double) : LocationBias()

Simulates GPS bias by offsetting locations to the left of the route direction. The f64 parameter specifies the offset distance in meters.

PropertyTypeDefaultDescription
val v1Double

LocationBias.Random

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Random(val v1: Double) : LocationBias()

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.

PropertyTypeDefaultDescription
val v1Double

LocationBias.Right

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Right(val v1: Double) : LocationBias()

Simulates GPS bias by offsetting locations to the right of the route direction. The f64 parameter specifies the offset distance in meters.

PropertyTypeDefaultDescription
val v1Double

LocationSimulationState

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class LocationSimulationState (var currentLocation: UserLocation, var remainingLocations: List<GeographicCoordinate>, var bias: LocationBias)

The current state of the simulation.

PropertyTypeDefaultDescription
var currentLocationUserLocation
var remainingLocationsList<GeographicCoordinate>
var biasLocationBias

ManualStepCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class ManualStepCondition: Disposable, AutoCloseable, ManualStepConditionInterface

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.

Initialisers and methods

  • override fun destroy()
  • override fun close()

ModelException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class ModelException: Exception()

Nested: ModelException.PolylineGenerationException, ModelException.ErrorHandler.

ModelException.PolylineGenerationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class PolylineGenerationException(val error: String) : ModelException()
PropertyTypeDefaultDescription
val errorString
val message

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationCacheImpl: Disposable, AutoCloseable, NavigationCache

Initialisers and methods

  • override fun destroy()
  • override fun close()
  • override fun save(record: ByteArray)
  • override fun load(): ByteArray?
  • override fun delete()

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class NavigationCachingConfig (var cacheIntervalSeconds: Long, var maxAgeSeconds: Long)
PropertyTypeDefaultDescription
var cacheIntervalSecondsLong
var maxAgeSecondsLong

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationController: Disposable, AutoCloseable, NavigationControllerInterface

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

  • constructor(route: Route, config: NavigationControllerConfig): Create a navigation controller for a route and configuration.
  • override fun destroy()
  • override fun close()

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class NavigationControllerConfig (var waypointAdvance: WaypointAdvanceMode, var stepAdvanceCondition: StepAdvanceCondition, var arrivalStepAdvanceCondition: StepAdvanceCondition, var routeDeviationTracking: RouteDeviationTracking, var snappedLocationCourseFiltering: CourseFiltering): Disposable
PropertyTypeDefaultDescription
var waypointAdvanceWaypointAdvanceMode
var stepAdvanceConditionStepAdvanceCondition
var arrivalStepAdvanceConditionStepAdvanceCondition
var routeDeviationTrackingRouteDeviationTracking
var snappedLocationCourseFilteringCourseFiltering

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationObserverImpl: Disposable, AutoCloseable, NavigationObserver

Initialisers and methods

  • override fun destroy()
  • override fun close()
  • override fun onGetInitialState(state: NavState)
  • override fun onUserLocationUpdate(location: UserLocation, state: NavState)
  • override fun onAdvanceToNextStep(state: NavState)
  • override fun onRouteAvailable(route: Route)

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationRecorder: Disposable, AutoCloseable, NavigationRecorderInterface

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class NavigationRecordingEvent (var timestamp: Long, var eventData: NavigationRecordingEventData)

An event that occurs during navigation.

This is used for the optional session recording / telemetry.

PropertyTypeDefaultDescription
var timestampLong
var eventDataNavigationRecordingEventData

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class NavigationRecordingEventData

The event type.

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

Nested: NavigationRecordingEventData.StateUpdate, NavigationRecordingEventData.RouteUpdate.

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class RouteUpdate(val route: uniffi.ferrostar.Route) : NavigationRecordingEventData()
PropertyTypeDefaultDescription
val routeuniffi.ferrostar.Route

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class StateUpdate(val tripState: uniffi.ferrostar.TripState, val stepAdvanceCondition: uniffi.ferrostar.SerializableStepAdvanceCondition) : NavigationRecordingEventData()
PropertyTypeDefaultDescription
val tripStateuniffi.ferrostar.TripState
val stepAdvanceConditionuniffi.ferrostar.SerializableStepAdvanceCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationReplay: Disposable, AutoCloseable, NavigationReplayInterface

A wrapper around NavigationRecording to facilitate replaying the event stream.

Initialisers and methods

  • override fun destroy()
  • override fun close()

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationSession: Disposable, AutoCloseable, NavigationSessionInterface

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class NavigationSessionCache: Disposable, AutoCloseable, NavigationSessionCacheInterface

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class NavigationSessionSnapshot (var savedAt: UtcDateTime, var route: Route, var tripState: TripState?)
PropertyTypeDefaultDescription
var savedAtUtcDateTime
var routeRoute
var tripStateTripState?

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class Navigator: Disposable, AutoCloseable, NavigatorInterface

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

  • override fun destroy()
  • override fun close()
  • override fun route(): Route
  • override fun getInitialState(location: UserLocation): NavState
  • override fun advanceToNextStep(state: NavState): NavState
  • override fun updateUserLocation(location: UserLocation, state: NavState): NavState

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class NavState (var tripState: TripState, var stepAdvanceCondition: StepAdvanceCondition): Disposable

The navigation state.

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

PropertyTypeDefaultDescription
var tripStateTripState
var stepAdvanceConditionStepAdvanceCondition

OrAdvanceConditions

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class OrAdvanceConditions: Disposable, AutoCloseable, OrAdvanceConditionsInterface

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

This is ideal for short circuit type advance conditions.

E.g. you may have:

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

Initialisers and methods

  • override fun destroy()
  • override fun close()

OsrmWaypointProperties

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class OsrmWaypointProperties (var name: String?, var distance: Double?)

Waypoint properties parsed from an OSRM-compatible server response.

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

PropertyTypeDefaultDescription
var nameString?
var distanceDouble?

ParsingException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class ParsingException: Exception()

Nested: ParsingException.InvalidRouteObject, ParsingException.InvalidGeometry, ParsingException.MalformedAnnotations, ParsingException.InvalidStatusCode, ParsingException.UnknownParsingException, ParsingException.ErrorHandler.

ParsingException.InvalidGeometry

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class InvalidGeometry(val error: String) : ParsingException()
PropertyTypeDefaultDescription
val errorString
val message

ParsingException.InvalidRouteObject

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class InvalidRouteObject(val error: String) : ParsingException()
PropertyTypeDefaultDescription
val errorString
val message

ParsingException.InvalidStatusCode

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class InvalidStatusCode(val code: String, val description: String?) : ParsingException()
PropertyTypeDefaultDescription
val codeString
val descriptionString?
val message

ParsingException.MalformedAnnotations

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class MalformedAnnotations(val error: String) : ParsingException()
PropertyTypeDefaultDescription
val errorString
val message

ParsingException.UnknownParsingException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class UnknownParsingException() : ParsingException()
PropertyTypeDefaultDescription
val message

RecordingException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class RecordingException: Exception()

A session recording error.

Nested: RecordingException.SerializationException, RecordingException.RecordingNotEnabled, RecordingException.DeserializationException, RecordingException.ErrorHandler.

RecordingException.DeserializationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class DeserializationException(val error: String) : RecordingException()

Error during deserialization.

PropertyTypeDefaultDescription
val errorString
val message

RecordingException.RecordingNotEnabled

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class RecordingNotEnabled() : RecordingException()

Recording is not enabled for this controller.

PropertyTypeDefaultDescription
val message

RecordingException.SerializationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class SerializationException(val error: String) : RecordingException()

Error during serialization.

PropertyTypeDefaultDescription
val errorString
val message

Route

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Route (var geometry: List<GeographicCoordinate>, var bbox: BoundingBox, var distance: Double, var waypoints: List<Waypoint>, var steps: List<RouteStep>)

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

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

PropertyTypeDefaultDescription
var geometryList<GeographicCoordinate>
var bboxBoundingBox
var distanceDouble
var waypointsList<Waypoint>
var stepsList<RouteStep>

RouteAdapter

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class RouteAdapter: Disposable, AutoCloseable, RouteAdapterInterface

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

  • constructor(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.
  • override fun destroy()
  • override fun close()
  • @Throws(RoutingRequestGenerationException::class) override fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequest
  • @Throws(ParsingException::class) override fun parseResponse(response: ByteArray): List<Route>

Nested: RouteAdapter.Companion.

RouteDeviation

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class RouteDeviation

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.

Nested: RouteDeviation.NoDeviation, RouteDeviation.Deviation.

RouteDeviation.Deviation

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Deviation(val kind: uniffi.ferrostar.DeviationKind) : RouteDeviation()

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.

PropertyTypeDefaultDescription
val kinduniffi.ferrostar.DeviationKind

RouteDeviationDetectorImpl

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class RouteDeviationDetectorImpl: Disposable, AutoCloseable, RouteDeviationDetector

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

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

RouteDeviationTracking

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class RouteDeviationTracking: Disposable

Determines if the user has deviated from the expected route.

Initialisers and methods

  • override fun destroy()

Nested: RouteDeviationTracking.None, RouteDeviationTracking.StaticThreshold, RouteDeviationTracking.Custom.

RouteDeviationTracking.Custom

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Custom(val detector: uniffi.ferrostar.RouteDeviationDetector) : RouteDeviationTracking()

An arbitrary user-defined implementation. You decide with your own RouteDeviationDetector implementation!

PropertyTypeDefaultDescription
val detectoruniffi.ferrostar.RouteDeviationDetector

RouteDeviationTracking.StaticThreshold

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class StaticThreshold(val minimumHorizontalAccuracy: UShort, val maxAcceptableDeviation: Double) : RouteDeviationTracking()

Detects deviation from the route using a configurable static distance threshold from the route line.

PropertyTypeDefaultDescription
val minimumHorizontalAccuracyUShort
val maxAcceptableDeviationDouble

RouteRequest

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class RouteRequest

A route request generated by a RouteRequestGenerator.

Nested: RouteRequest.HttpPost, RouteRequest.HttpGet.

RouteRequest.HttpGet

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class HttpGet(val url: String, val headers: Map<String, String>) : RouteRequest()
PropertyTypeDefaultDescription
val urlString
val headersMap<String, String>

RouteRequest.HttpPost

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class HttpPost(val url: String, val headers: Map<String, String>, val body: ByteArray) : RouteRequest()
PropertyTypeDefaultDescription
val urlString
val headersMap<String, String>
val bodyByteArray

RouteRequestGeneratorImpl

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class RouteRequestGeneratorImpl: Disposable, AutoCloseable, RouteRequestGenerator

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

  • override fun destroy()
  • override fun close()
  • @Throws(RoutingRequestGenerationException::class) override fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
open class RouteResponseParserImpl: Disposable, AutoCloseable, RouteResponseParser

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

Initialisers and methods

  • override fun destroy()
  • override fun close()
  • @Throws(ParsingException::class) override fun parseResponse(response: ByteArray): List<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.).

RouteStep

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class RouteStep (var geometry: List<GeographicCoordinate>, var distance: Double, var duration: Double, var roadName: String?, var exits: List<String>, var instruction: String, var visualInstructions: List<VisualInstruction>, var spokenInstructions: List<SpokenInstruction>, var annotations: List<String>?, var incidents: List<Incident>, var drivingSide: DrivingSide?, var roundaboutExitNumber: UByte?)

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

PropertyTypeDefaultDescription
var geometryList<GeographicCoordinate>
var distanceDouble
var durationDouble
var roadNameString?
var exitsList<String>
var instructionString
var visualInstructionsList<VisualInstruction>
var spokenInstructionsList<SpokenInstruction>
var annotationsList<String>?
var incidentsList<Incident>
var drivingSideDrivingSide?
var roundaboutExitNumberUByte?

RoutingRequestGenerationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class RoutingRequestGenerationException: Exception()

Nested: RoutingRequestGenerationException.NotEnoughWaypoints, RoutingRequestGenerationException.JsonException, RoutingRequestGenerationException.UnknownRequestGenerationException, RoutingRequestGenerationException.ErrorHandler.

RoutingRequestGenerationException.JsonException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class JsonException() : RoutingRequestGenerationException()
PropertyTypeDefaultDescription
val message

RoutingRequestGenerationException.NotEnoughWaypoints

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class NotEnoughWaypoints() : RoutingRequestGenerationException()
PropertyTypeDefaultDescription
val message

RoutingRequestGenerationException.UnknownRequestGenerationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class UnknownRequestGenerationException() : RoutingRequestGenerationException()
PropertyTypeDefaultDescription
val message

SerializableNavState

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class SerializableNavState (var tripState: TripState, var stepAdvanceCondition: SerializableStepAdvanceCondition)
PropertyTypeDefaultDescription
var tripStateTripState
var stepAdvanceConditionSerializableStepAdvanceCondition

SerializableStepAdvanceCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class SerializableStepAdvanceCondition

Nested: SerializableStepAdvanceCondition.Manual, SerializableStepAdvanceCondition.DistanceToEndOfStep, SerializableStepAdvanceCondition.DistanceFromStep, SerializableStepAdvanceCondition.DistanceEntryExit, SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit, SerializableStepAdvanceCondition.OrAdvanceConditions, SerializableStepAdvanceCondition.AndAdvanceConditions.

SerializableStepAdvanceCondition.AndAdvanceConditions

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class AndAdvanceConditions(val conditions: List<uniffi.ferrostar.SerializableStepAdvanceCondition>) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val conditionsList<uniffi.ferrostar.SerializableStepAdvanceCondition>

SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class DistanceEntryAndSnappedExit(val distanceToEndOfStep: UShort, val distanceAfterEndStep: UShort, val minimumHorizontalAccuracy: UShort, val hasReachedEndOfCurrentStep: Boolean) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val distanceToEndOfStepUShort
val distanceAfterEndStepUShort
val minimumHorizontalAccuracyUShort
val hasReachedEndOfCurrentStepBoolean

SerializableStepAdvanceCondition.DistanceEntryExit

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class DistanceEntryExit(val distanceToEndOfStep: UShort, val distanceAfterEndStep: UShort, val minimumHorizontalAccuracy: UShort, val hasReachedEndOfCurrentStep: Boolean) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val distanceToEndOfStepUShort
val distanceAfterEndStepUShort
val minimumHorizontalAccuracyUShort
val hasReachedEndOfCurrentStepBoolean

SerializableStepAdvanceCondition.DistanceFromStep

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class DistanceFromStep(val distance: UShort, val minimumHorizontalAccuracy: UShort, val calculationPolicy: uniffi.ferrostar.DeviationCalculationPolicy) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val distanceUShort
val minimumHorizontalAccuracyUShort
val calculationPolicyuniffi.ferrostar.DeviationCalculationPolicy

SerializableStepAdvanceCondition.DistanceToEndOfStep

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class DistanceToEndOfStep(val distance: UShort, val minimumHorizontalAccuracy: UShort) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val distanceUShort
val minimumHorizontalAccuracyUShort

SerializableStepAdvanceCondition.OrAdvanceConditions

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class OrAdvanceConditions(val conditions: List<uniffi.ferrostar.SerializableStepAdvanceCondition>) : SerializableStepAdvanceCondition()
PropertyTypeDefaultDescription
val conditionsList<uniffi.ferrostar.SerializableStepAdvanceCondition>

SimulationException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class SimulationException: Exception()

Nested: SimulationException.PolylineException, SimulationException.NotEnoughPoints, SimulationException.ErrorHandler.

SimulationException.NotEnoughPoints

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class NotEnoughPoints() : SimulationException()

Not enough points in the input.

PropertyTypeDefaultDescription
val message

SimulationException.PolylineException

Class · uniffi/ferrostar/ferrostar.kt

kotlin
class PolylineException(val error: String) : SimulationException()

Errors decoding the polyline string.

PropertyTypeDefaultDescription
val errorString
val message

Speed

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Speed (var value: Double, var accuracy: Double?)

The speed of the user from the location provider.

PropertyTypeDefaultDescription
var valueDouble
var accuracyDouble?

SpokenInstruction

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class SpokenInstruction (var text: String, var ssml: String?, var triggerDistanceBeforeManeuver: Double, var utteranceId: Uuid)

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

Note that these do not have any locale information attached.

PropertyTypeDefaultDescription
var textString
var ssmlString?
var triggerDistanceBeforeManeuverDouble
var utteranceIdUuid

StepAdvanceCondition

Class · uniffi/ferrostar/ferrostar.kt

kotlin
open class StepAdvanceCondition: Disposable, AutoCloseable, StepAdvanceConditionInterface

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

  • override fun destroy()
  • override fun close()
  • override fun 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.
  • override fun 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.

StepAdvanceResult

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class StepAdvanceResult (var shouldAdvance: Boolean, var nextIteration: StepAdvanceCondition): Disposable

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

PropertyTypeDefaultDescription
var shouldAdvanceBoolean
var nextIterationStepAdvanceCondition

TripProgress

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class TripProgress (var distanceToNextManeuver: Double, var distanceRemaining: Double, var durationRemaining: Double)

High-level state describing progress through a route.

PropertyTypeDefaultDescription
var distanceToNextManeuverDouble
var distanceRemainingDouble
var durationRemainingDouble

TripState

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class TripState

The state of a navigation session.

This is produced by NavigationController methods including get_initial_state and update_user_location.

Nested: TripState.Idle, TripState.Navigating, TripState.Complete.

TripState.Complete

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Complete(val userLocation: uniffi.ferrostar.UserLocation, val summary: uniffi.ferrostar.TripSummary) : TripState()

The navigation controller has reached the end of the trip.

PropertyTypeDefaultDescription
val userLocationuniffi.ferrostar.UserLocation
val summaryuniffi.ferrostar.TripSummary

TripState.Idle

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Idle(val userLocation: uniffi.ferrostar.UserLocation?) : TripState()

The navigation controller is idle and there is no active trip.

PropertyTypeDefaultDescription
val userLocationuniffi.ferrostar.UserLocation?

TripState.Navigating

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Navigating(val currentStepGeometryIndex: ULong?, val userLocation: uniffi.ferrostar.UserLocation, val snappedUserLocation: uniffi.ferrostar.UserLocation, val remainingSteps: List<uniffi.ferrostar.RouteStep>, val remainingWaypoints: List<uniffi.ferrostar.Waypoint>, val progress: uniffi.ferrostar.TripProgress, val summary: uniffi.ferrostar.TripSummary, val deviation: uniffi.ferrostar.RouteDeviation, val visualInstruction: uniffi.ferrostar.VisualInstruction?, val spokenInstruction: uniffi.ferrostar.SpokenInstruction?, val annotationJson: String?) : TripState()

The navigation controller is actively navigating a trip.

PropertyTypeDefaultDescription
val currentStepGeometryIndexULong?
val userLocationuniffi.ferrostar.UserLocation
val snappedUserLocationuniffi.ferrostar.UserLocation
val remainingStepsList<uniffi.ferrostar.RouteStep>
val remainingWaypointsList<uniffi.ferrostar.Waypoint>
val progressuniffi.ferrostar.TripProgress
val summaryuniffi.ferrostar.TripSummary
val deviationuniffi.ferrostar.RouteDeviation
val visualInstructionuniffi.ferrostar.VisualInstruction?
val spokenInstructionuniffi.ferrostar.SpokenInstruction?
val annotationJsonString?

TripSummary

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class TripSummary (var distanceTraveled: Double, var snappedDistanceTraveled: Double, var startedAt: UtcDateTime, var endedAt: UtcDateTime?)

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

PropertyTypeDefaultDescription
var distanceTraveledDouble
var snappedDistanceTraveledDouble
var startedAtUtcDateTime
var endedAtUtcDateTime?

UserLocation

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class UserLocation (var coordinates: GeographicCoordinate, var horizontalAccuracy: Double, var courseOverGround: CourseOverGround?, var timestamp: java.time.Instant, var speed: Speed?)

The location of the user that is navigating.

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

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

PropertyTypeDefaultDescription
var coordinatesGeographicCoordinate
var horizontalAccuracyDouble
var courseOverGroundCourseOverGround?
var timestampjava.time.Instant
var speedSpeed?

ValhallaLocationSearchFilter

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class ValhallaLocationSearchFilter (var excludeTunnel: Boolean? = null, var excludeBridge: Boolean? = null, var excludeTolls: Boolean? = null, var excludeFerry: Boolean? = null, var excludeRamp: Boolean? = null, var excludeClosures: Boolean? = null, var minRoadClass: ValhallaRoadClass? = null, var maxRoadClass: ValhallaRoadClass? = null, var level: Float? = null)

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

PropertyTypeDefaultDescription
var excludeTunnelBoolean?null
var excludeBridgeBoolean?null
var excludeTollsBoolean?null
var excludeFerryBoolean?null
var excludeRampBoolean?null
var excludeClosuresBoolean?null
var minRoadClassValhallaRoadClass?null
var maxRoadClassValhallaRoadClass?null
var levelFloat?null

ValhallaWaypointProperties

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class ValhallaWaypointProperties (var heading: UShort? = null, var headingTolerance: UShort? = null, var minimumReachability: UShort? = null, var radius: UShort? = null, var preferredSide: ValhallaWaypointPreferredSide? = null, var displayCoordinate: GeographicCoordinate? = null, var searchCutoff: UInt? = null, var nodeSnapTolerance: UShort? = null, var streetSideTolerance: UShort? = null, var streetSideMaxDistance: UShort? = null, var streetSideCutoff: ValhallaRoadClass? = null, var searchFilter: ValhallaLocationSearchFilter? = null, var allowUturns: Boolean? = null, var name: String? = null)

Waypoint properties supported by Valhalla servers.

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

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

PropertyTypeDefaultDescription
var headingUShort?null
var headingToleranceUShort?null
var minimumReachabilityUShort?null
var radiusUShort?null
var preferredSideValhallaWaypointPreferredSide?null
var displayCoordinateGeographicCoordinate?null
var searchCutoffUInt?null
var nodeSnapToleranceUShort?null
var streetSideToleranceUShort?null
var streetSideMaxDistanceUShort?null
var streetSideCutoffValhallaRoadClass?null
var searchFilterValhallaLocationSearchFilter?null
var allowUturnsBoolean?null
var nameString?null

VisualInstruction

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class VisualInstruction (var primaryContent: VisualInstructionContent, var secondaryContent: VisualInstructionContent?, var subContent: VisualInstructionContent?, var triggerDistanceBeforeManeuver: Double)

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

PropertyTypeDefaultDescription
var primaryContentVisualInstructionContent
var secondaryContentVisualInstructionContent?
var subContentVisualInstructionContent?
var triggerDistanceBeforeManeuverDouble

VisualInstructionContent

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class VisualInstructionContent (var text: String, var maneuverType: ManeuverType?, var maneuverModifier: ManeuverModifier?, var roundaboutExitDegrees: UShort?, var laneInfo: List<LaneInfo>?, var exitNumbers: List<String>)

The content of a visual instruction.

PropertyTypeDefaultDescription
var textString
var maneuverTypeManeuverType?
var maneuverModifierManeuverModifier?
var roundaboutExitDegreesUShort?
var laneInfoList<LaneInfo>?
var exitNumbersList<String>

Waypoint

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Waypoint (var coordinate: GeographicCoordinate, var kind: WaypointKind, var properties: ByteArray? = null)

A waypoint along a route.

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

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

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

PropertyTypeDefaultDescription
var coordinateGeographicCoordinate
var kindWaypointKind
var propertiesByteArray?null

WaypointAdvanceMode

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class WaypointAdvanceMode

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!

Nested: WaypointAdvanceMode.WaypointWithinRange, WaypointAdvanceMode.WaypointAlongAdvancingStep.

WaypointAdvanceMode.WaypointAlongAdvancingStep

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class WaypointAlongAdvancingStep(val v1: Double) : WaypointAdvanceMode()

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.

PropertyTypeDefaultDescription
val v1Double

WaypointAdvanceMode.WaypointWithinRange

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class WaypointWithinRange(val v1: Double) : WaypointAdvanceMode()

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.

PropertyTypeDefaultDescription
val v1Double

WellKnownRouteProvider

Class · uniffi/ferrostar/ferrostar.kt

kotlin
sealed class WellKnownRouteProvider

Configurations for built-in route providers.

Nested: WellKnownRouteProvider.Valhalla, WellKnownRouteProvider.GraphHopper.

WellKnownRouteProvider.GraphHopper

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class GraphHopper(val endpointUrl: String, val profile: String, val locale: String, val voiceUnits: uniffi.ferrostar.GraphHopperVoiceUnits, val optionsJson: String? = null) : WellKnownRouteProvider()

A GraphHopper-based routing API.

GraphHopper offers a commercially supported API. You can also substitute any other URL to use a self-hosted server.

PropertyTypeDefaultDescription
val endpointUrlString
val profileString
val localeString
val voiceUnitsuniffi.ferrostar.GraphHopperVoiceUnits
val optionsJsonString?null

WellKnownRouteProvider.Valhalla

Class · uniffi/ferrostar/ferrostar.kt

kotlin
data class Valhalla(val endpointUrl: String, val profile: String, val optionsJson: String? = null) : WellKnownRouteProvider()

A Valhalla-based routing API.

Stadia Maps offers a commercially supported API. You can also substitute any URL to use a self-hosted server.

PropertyTypeDefaultDescription
val endpointUrlString
val profileString
val optionsJsonString?null

Enums (uniffi.ferrostar)

BlockedLane, CourseFiltering, DeviationCalculationPolicy, DrivingSide, GraphHopperVoiceUnits, Impact, IncidentType, ManeuverModifier, ManeuverType, ValhallaRoadClass, ValhallaWaypointPreferredSide, WaypointKind

BlockedLane

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class BlockedLane

The lane type blocked by the incident.

CaseDescription
LEFT
LEFT_CENTER
LEFT_TURN_LANE
CENTER
RIGHT
RIGHT_CENTER
RIGHT_TURN_LANE
HOV

CourseFiltering

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class CourseFiltering

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

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

DeviationCalculationPolicy

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class DeviationCalculationPolicy

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

CaseDescription
ALWAYSAlways evaluate, regardless of deviation status.
WHILE_ON_ROUTEEvaluate 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.
WHILE_ON_CURRENT_STEPEvaluate 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).

DrivingSide

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class DrivingSide

Which side of the road traffic drives on.

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

CaseDescription
LEFT
RIGHT

GraphHopperVoiceUnits

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class GraphHopperVoiceUnits
CaseDescription
METRIC
IMPERIAL

Impact

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class Impact

The impact of the incident that has occurred.

CaseDescription
UNKNOWN
CRITICAL
MAJOR
MINOR
LOW

IncidentType

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class IncidentType

The type of incident that has occurred.

CaseDescription
ACCIDENT
CONGESTION
CONSTRUCTION
DISABLED_VEHICLE
LANE_RESTRICTION
MASS_TRANSIT
MISCELLANEOUS
OTHER_NEWS
PLANNED_EVENT
ROAD_CLOSURE
ROAD_HAZARD
WEATHER

ManeuverModifier

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class ManeuverModifier

Additional information to further specify a ManeuverType.

CaseDescription
U_TURN
SHARP_RIGHT
RIGHT
SLIGHT_RIGHT
STRAIGHT
SLIGHT_LEFT
LEFT
SHARP_LEFT

ManeuverType

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class ManeuverType

The broad class of maneuver to perform.

This is usually combined with ManeuverModifier in VisualInstructionContent.

CaseDescription
TURN
NEW_NAME
DEPART
ARRIVE
MERGE
ON_RAMP
OFF_RAMP
FORK
END_OF_ROAD
CONTINUE
ROUNDABOUT
ROTARY
ROUNDABOUT_TURN
NOTIFICATION
EXIT_ROUNDABOUT
EXIT_ROTARY

ValhallaRoadClass

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class ValhallaRoadClass

A road class in the Valhalla taxonomy.

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

CaseDescription
MOTORWAY
TRUNK
PRIMARY
SECONDARY
TERTIARY
UNCLASSIFIED
RESIDENTIAL
SERVICE_OTHER

ValhallaWaypointPreferredSide

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class ValhallaWaypointPreferredSide

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

Examples:

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

WaypointKind

Enum · uniffi/ferrostar/ferrostar.kt

kotlin
enum class WaypointKind

Describes characteristics of the waypoint for routing purposes.

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

Interfaces (uniffi.ferrostar)

AndAdvanceConditionsInterface, DistanceEntryAndExitConditionInterface, DistanceEntryAndSnappedExitConditionInterface, DistanceFromStepConditionInterface, DistanceToEndOfStepConditionInterface, ManualStepConditionInterface, NavigationCache, NavigationControllerInterface, NavigationObserver, NavigationRecorderInterface, NavigationReplayInterface, NavigationSessionCacheInterface, NavigationSessionInterface, NavigatorInterface, OrAdvanceConditionsInterface, RouteAdapterInterface, RouteDeviationDetector, RouteRequestGenerator, RouteResponseParser, StepAdvanceConditionInterface

AndAdvanceConditionsInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface AndAdvanceConditionsInterface

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

DistanceEntryAndExitConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface DistanceEntryAndExitConditionInterface

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

DistanceEntryAndSnappedExitConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface DistanceEntryAndSnappedExitConditionInterface

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.

DistanceFromStepConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface DistanceFromStepConditionInterface

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.

DistanceToEndOfStepConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface DistanceToEndOfStepConditionInterface

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.

ManualStepConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface ManualStepConditionInterface

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.

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationCache

Initialisers and methods

  • fun save(record: ByteArray)
  • fun load(): ByteArray?
  • fun delete()

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationControllerInterface

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.

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationObserver

Initialisers and methods

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

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationRecorderInterface

Initialisers and methods

  • fun getEvents(): List<NavigationRecordingEvent>
  • fun getRecordingJson(): String
  • fun onAdvanceToNextStep(state: NavState)
  • fun onGetInitialState(state: NavState)
  • fun onRouteAvailable(route: Route)
  • fun onUserLocationUpdate(location: UserLocation, state: NavState)

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationReplayInterface

A wrapper around NavigationRecording to facilitate replaying the event stream.

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationSessionCacheInterface

Initialisers and methods

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

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigationSessionInterface

Initialisers and methods

  • fun advanceToNextStep(state: NavState): NavState
  • fun getInitialState(location: UserLocation): NavState
  • fun route(): Route
  • fun updateUserLocation(location: UserLocation, state: NavState): NavState

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface NavigatorInterface

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

  • fun route(): Route
  • fun getInitialState(location: UserLocation): NavState
  • fun advanceToNextStep(state: NavState): NavState
  • fun updateUserLocation(location: UserLocation, state: NavState): NavState

OrAdvanceConditionsInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface OrAdvanceConditionsInterface

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

This is ideal for short circuit type advance conditions.

E.g. you may have:

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

RouteAdapterInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface RouteAdapterInterface

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

  • fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequest
  • fun parseResponse(response: ByteArray): List<Route>

RouteDeviationDetector

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface RouteDeviationDetector

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

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

RouteRequestGenerator

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface RouteRequestGenerator

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

  • fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): 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

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface RouteResponseParser

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

Initialisers and methods

  • fun parseResponse(response: ByteArray): List<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.).

StepAdvanceConditionInterface

Interface · uniffi/ferrostar/ferrostar.kt

kotlin
public interface StepAdvanceConditionInterface

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

  • fun 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.
  • fun 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.

Objects (uniffi.ferrostar)

InstantiationException.ErrorHandler, LocationBias.None, ModelException.ErrorHandler, ParsingException.ErrorHandler, RecordingException.ErrorHandler, RouteAdapter.Companion, RouteDeviation.NoDeviation, RouteDeviationTracking.None, RoutingRequestGenerationException.ErrorHandler, SerializableStepAdvanceCondition.Manual, SimulationException.ErrorHandler

InstantiationException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<InstantiationException>

LocationBias.None

Object · uniffi/ferrostar/ferrostar.kt

kotlin
object None : LocationBias()

No position bias - locations follow the route line exactly.

This provides "perfect" GPS behavior, useful for testing basic route following without position uncertainty.

ModelException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<ModelException>

ParsingException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<ParsingException>

RecordingException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<RecordingException>

RouteAdapter.Companion

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object

Initialisers and methods

  • @Throws(InstantiationException::class) fun fromWellKnownRouteProvider(wellKnownRouteProvider: WellKnownRouteProvider): RouteAdapter: Creates a route adapter from a well-known provider configuration.

RouteDeviation.NoDeviation

Object · uniffi/ferrostar/ferrostar.kt

kotlin
object NoDeviation : RouteDeviation()

The user is proceeding on course within the expected tolerances; everything is normal.

RouteDeviationTracking.None

Object · uniffi/ferrostar/ferrostar.kt

kotlin
object None : RouteDeviationTracking()

No checks will be done, and we assume the user is always following the route.

RoutingRequestGenerationException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<RoutingRequestGenerationException>

SerializableStepAdvanceCondition.Manual

Object · uniffi/ferrostar/ferrostar.kt

kotlin
object Manual : SerializableStepAdvanceCondition()

SimulationException.ErrorHandler

Object · uniffi/ferrostar/ferrostar.kt

kotlin
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<SimulationException>

Functions (uniffi.ferrostar)

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

advanceLocationSimulation

Function · uniffi/ferrostar/ferrostar.kt

kotlin
fun 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.

createNavigationSession

Function · uniffi/ferrostar/ferrostar.kt

kotlin
fun createNavigationSession(route: Route, config: NavigationControllerConfig, observers: List<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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun createNavigator(route: Route, config: NavigationControllerConfig, shouldRecord: Boolean): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun createOsrmResponseParser(polylinePrecision: UInt): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(ParsingException::class) fun createRouteFromOsrm(routeData: ByteArray, waypointData: ByteArray, polylinePrecision: UInt): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(ParsingException::class) fun createRouteFromOsrmRoute(routeData: ByteArray, waypoints: List<Waypoint>, polylinePrecision: UInt): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(InstantiationException::class) fun createValhallaRequestGenerator(endpointUrl: String, profile: String, optionsJson: String?): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(ModelException::class) fun getRoutePolyline(route: Route, precision: UInt): String

Helper function for getting the route as an encoded polyline.

Mostly used for debugging.

locationSimulationFromCoordinates

Function · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(SimulationException::class) fun locationSimulationFromCoordinates(coordinates: List<GeographicCoordinate>, resampleDistance: Double?, bias: LocationBias): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(SimulationException::class) fun locationSimulationFromPolyline(polyline: String, precision: UInt, resampleDistance: Double?, bias: LocationBias): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
@Throws(SimulationException::class) fun locationSimulationFromRoute(route: Route, resampleDistance: Double?, bias: LocationBias): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceAnd(conditions: List<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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceDistanceEntryAndExit(distanceToEndOfStep: UShort, distanceAfterEndOfStep: UShort, minimumHorizontalAccuracy: UShort): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceDistanceEntryAndSnappedExit(distanceToEndOfStep: UShort, distanceAfterEndOfStep: UShort, minimumHorizontalAccuracy: UShort): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceDistanceFromStep(distance: UShort, minimumHorizontalAccuracy: UShort, 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceDistanceToEndOfStep(distance: UShort, minimumHorizontalAccuracy: UShort): 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun 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 · uniffi/ferrostar/ferrostar.kt

kotlin
fun stepAdvanceOr(conditions: List<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 (uniffi.ferrostar)

UtcDateTime, Uuid

UtcDateTime

Type alias · uniffi/ferrostar/ferrostar.kt

kotlin
public typealias UtcDateTime = java.util.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. It's also what we have an external type that references a custom type.

Uuid

Type alias · uniffi/ferrostar/ferrostar.kt

kotlin
public typealias Uuid = java.util.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. It's also what we have an external type that references a custom type.