Docs/API Reference/Predicates

Predicates

The three predicate methods on OctetSdk.loc. All three are async (Swift) / suspend (Kotlin) and do not throw. Runtime problems surface as INDETERMINATE verdicts, not exceptions.

isWithin

The primary predicate. Reads as: "my currently provable location is inside region."

public func isWithin(
    region: OctetRegion,
    atTime: Date = Date()
) async -> OctetVerdict
suspend fun isWithin(
    region: OctetRegion,
    atTime: Instant = Instant.now(),
): OctetVerdict

Example

let v = await sdk.loc.isWithin(
    region: .country(isoCode: "US"),
    atTime: Date()
)
if v.result == .yes { ship(v.proof!) }
val v = sdk.loc.isWithin(
    region = OctetRegion.country("US"),
    atTime = Instant.now()
)
if (v.result == OctetVerdict.Result.YES) ship(v.proof!!)

isOutside

Reads as: "my currently provable location is outside region."

public func isOutside(
    region: OctetRegion,
    atTime: Date = Date()
) async -> OctetVerdict
suspend fun isOutside(
    region: OctetRegion,
    atTime: Instant = Instant.now(),
): OctetVerdict
Caution

isOutside is not !isWithin. An INDETERMINATE is not outside. The separate call lets the caller assert the negative claim and get a proof of the negative. A verifier can check that proof just as easily as a YES. Negating an INDETERMINATE would erase the difference between "I'm not inside" and "I can't tell".


contains

Reads from the device's perspective: "my location contains this point within tol meters."

public func contains(
    center: LatLon,
    tol: Meters,
    atTime: Date = Date()
) async -> OctetVerdict
suspend fun contains(
    center: LatLon,
    tol: Meters,
    atTime: Instant = Instant.now(),
): OctetVerdict

Mathematically equivalent to isWithin(region: .disc(center: center, radiusMeters: tol), atTime:). Kept as a distinct verb because the device-centric reading is the natural one for proximity use cases ("am I near the delivery dropoff", "did I arrive at the geofence").

Rolling your own

isWithin is the load-bearing primitive. contains is a thin one-liner over it. The same trick rolls custom predicates:

extension OctetLoc {
    func isNear(_ center: LatLon, _ tol: Meters) async -> OctetVerdict {
        await isWithin(region: .disc(center: center, radiusMeters: tol))
    }
    func isInsideAny(_ regions: [OctetRegion]) async -> OctetVerdict? {
        for r in regions {
            let v = await isWithin(region: r)
            if v.result == .yes { return v }
        }
        return nil
    }
}
suspend fun OctetLoc.isNear(center: LatLon, tol: Meters): OctetVerdict =
    isWithin(OctetRegion.disc(center, tol))

suspend fun OctetLoc.isInsideAny(regions: List<OctetRegion>): OctetVerdict? {
    for (r in regions) {
        val v = isWithin(r)
        if (v.result == OctetVerdict.Result.YES) return v
    }
    return null
}

Time semantics

All three predicates take an optional atTime. See Time Semantics for the live / historical / future regimes and the per-resolution validity windows. Default is "now". Future times beyond ±2 s come back INDETERMINATE / FUTURE_TIME.

See also