Files
Luma/Sources/Shared/Models/GeoLocation.swift
T
2026-07-30 20:07:51 +07:00

62 lines
2.2 KiB
Swift

import Foundation
struct GeoLocation: Equatable, Sendable {
let latitude: Double
let longitude: Double
let uncertainty: Double?
init?(latitude: Double, longitude: Double, uncertainty: Double? = nil) {
guard latitude.isFinite,
longitude.isFinite,
(-90...90).contains(latitude),
(-180...180).contains(longitude) else { return nil }
if let uncertainty, (!uncertainty.isFinite || uncertainty < 0) {
return nil
}
self.latitude = latitude
self.longitude = longitude
self.uncertainty = uncertainty
}
init?(uri: String) {
let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
guard trimmed.lowercased().hasPrefix("geo:") else { return nil }
let payload = trimmed.dropFirst(4)
let components = payload.split(separator: ";", omittingEmptySubsequences: false)
guard let coordinatePart = components.first else { return nil }
let coordinates = coordinatePart.split(separator: ",", omittingEmptySubsequences: false)
guard coordinates.count == 2 || coordinates.count == 3,
let latitude = Double(coordinates[0]),
let longitude = Double(coordinates[1]) else { return nil }
if coordinates.count == 3, Double(coordinates[2]) == nil {
return nil
}
var uncertainty: Double?
for component in components.dropFirst() {
let pair = component.split(separator: "=", maxSplits: 1)
guard pair.count == 2 else { continue }
if pair[0].lowercased() == "u" {
guard let value = Double(pair[1]) else { return nil }
uncertainty = value
}
}
self.init(latitude: latitude, longitude: longitude, uncertainty: uncertainty)
}
var uriString: String {
let coordinates = String(
format: "geo:%.6f,%.6f",
locale: Locale(identifier: "en_US_POSIX"),
latitude,
longitude
)
guard let uncertainty else { return coordinates }
return coordinates + String(
format: ";u=%.0f",
locale: Locale(identifier: "en_US_POSIX"),
uncertainty
)
}
}