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."
- Swift (iOS)
- Kotlin (Android)
public func isWithin(
region: OctetRegion,
atTime: Date = Date()
) async -> OctetVerdict
suspend fun isWithin(
region: OctetRegion,
atTime: Instant = Instant.now(),
): OctetVerdict
Example
- Swift (iOS)
- Kotlin (Android)
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."
- Swift (iOS)
- Kotlin (Android)
public func isOutside(
region: OctetRegion,
atTime: Date = Date()
) async -> OctetVerdict
suspend fun isOutside(
region: OctetRegion,
atTime: Instant = Instant.now(),
): OctetVerdict
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."
- Swift (iOS)
- Kotlin (Android)
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:
- Swift (iOS)
- Kotlin (Android)
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
OctetRegion. The shapes you can pass.OctetVerdict. What you get back.- Verdicts. The trichotomy and the
ReasonCodetaxonomy.