Skip to content

Commit

Permalink
Simplified Core Location shim for Linux
Browse files Browse the repository at this point in the history
Rewrote the Core Location compatibility shim for Linux with a single type, LocationCoordinate2D, that uses only standard library types and avoids any naming collision with Core Location types. Added a single type alias so that Apple platforms can use CLLocationCoordinate2D in place of the compatibility shim.

Excluded anything involving CLLocation from Linux; clients can provide their own class to wrap LocationCoordinate2D if desired.
  • Loading branch information
1ec5 committed Nov 3, 2020
1 parent 4f879da commit f0553ac
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 43 deletions.
50 changes: 15 additions & 35 deletions Sources/Polyline/CoreLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,20 @@
// SOFTWARE.

import Foundation


#if !canImport(CoreLocation)
public typealias CLLocationDegrees = Double
public typealias CLLocationSpeed = Double
public typealias CLLocationDirection = Double
public typealias CLLocationDistance = Double
public typealias CLLocationAccuracy = Double

public struct CLLocationCoordinate2D {
public let latitude: CLLocationDegrees
public let longitude: CLLocationDegrees
}

public struct CLLocation {
public let coordinate: CLLocationCoordinate2D
public let horizontalAccuracy: CLLocationAccuracy
public let verticalAccuracy: CLLocationAccuracy
public let speed: CLLocationSpeed
public let course: CLLocationDirection
public let timestamp: Date

public init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
self.horizontalAccuracy = -1
self.verticalAccuracy = -1
self.speed = -1
self.course = -1
self.timestamp = Date()
}

public init(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
self.init(coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
#if canImport(CoreLocation)
import CoreLocation
#endif

#if canImport(CoreLocation)
public typealias LocationCoordinate2D = CLLocationCoordinate2D
#else
public struct LocationCoordinate2D: CoordinateRepresentable {
let latitude: Double
let longitude: Double

public init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}

#endif
#endif
26 changes: 18 additions & 8 deletions Sources/Polyline/Polyline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import MapKit
public struct Polyline {

/// The array of coordinates (nil if polyline cannot be decoded)
public let coordinates: [CLLocationCoordinate2D]?
public let coordinates: [LocationCoordinate2D]?
/// The encoded polyline
public let encodedPolyline: String

Expand All @@ -55,9 +55,11 @@ public struct Polyline {
public let encodedLevels: String?

/// The array of location (computed from coordinates)
#if canImport(CoreLocation)
public var locations: [CLLocation]? {
return self.coordinates.map(toLocations)
}
#endif

#if canImport(MapKit)
/// Convert polyline to MKPolyline to use with MapKit (nil if polyline cannot be decoded)
Expand All @@ -73,10 +75,10 @@ public struct Polyline {

/// This designated initializer encodes a `[CLLocationCoordinate2D]`
///
/// - parameter coordinates: The `Array` of `CLLocationCoordinate2D` that you want to encode
/// - parameter coordinates: The `Array` of `LocationCoordinate2D`s (that is, `CLLocationCoordinate2D`s) that you want to encode
/// - parameter levels: The optional `Array` of levels that you want to encode (default: `nil`)
/// - parameter precision: The precision used for encoding (default: `1e5`)
public init(coordinates: [CLLocationCoordinate2D], levels: [UInt32]? = nil, precision: Double = 1e5) {
public init(coordinates: [LocationCoordinate2D], levels: [UInt32]? = nil, precision: Double = 1e5) {

self.coordinates = coordinates
self.levels = levels
Expand All @@ -101,6 +103,7 @@ public struct Polyline {
levels = self.encodedLevels.flatMap(decodeLevels)
}

#if canImport(CoreLocation)
/// This init encodes a `[CLLocation]`
///
/// - parameter locations: The `Array` of `CLLocation` that you want to encode
Expand All @@ -111,17 +114,18 @@ public struct Polyline {
let coordinates = toCoordinates(locations)
self.init(coordinates: coordinates, levels: levels, precision:precision)
}
#endif
}

// MARK: - Public Functions -

/// This function encodes an `[CLLocationCoordinate2D]` to a `String`
///
/// - parameter coordinates: The `Array` of `CLLocationCoordinate2D` that you want to encode
/// - parameter coordinates: The `Array` of `LocationCoordinate2D`s (that is, `CLLocationCoordinate2D`s) that you want to encode
/// - parameter precision: The precision used to encode coordinates (default: `1e5`)
///
/// - returns: A `String` representing the encoded Polyline
public func encodeCoordinates(_ coordinates: [CLLocationCoordinate2D], precision: Double = 1e5) -> String {
public func encodeCoordinates(_ coordinates: [LocationCoordinate2D], precision: Double = 1e5) -> String {

var previousCoordinate = IntegerCoordinates(0, 0)
var encodedPolyline = ""
Expand All @@ -140,6 +144,7 @@ public func encodeCoordinates(_ coordinates: [CLLocationCoordinate2D], precision
return encodedPolyline
}

#if canImport(CoreLocation)
/// This function encodes an `[CLLocation]` to a `String`
///
/// - parameter coordinates: The `Array` of `CLLocation` that you want to encode
Expand All @@ -150,6 +155,7 @@ public func encodeLocations(_ locations: [CLLocation], precision: Double = 1e5)

return encodeCoordinates(toCoordinates(locations), precision: precision)
}
#endif

/// This function encodes an `[UInt32]` to a `String`
///
Expand All @@ -168,15 +174,15 @@ public func encodeLevels(_ levels: [UInt32]) -> String {
/// - parameter precision: The precision used to decode coordinates (default: `1e5`)
///
/// - returns: A `[CLLocationCoordinate2D]` representing the decoded polyline if valid, `nil` otherwise
public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -> [CLLocationCoordinate2D]? {
public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -> [LocationCoordinate2D]? {

let data = encodedPolyline.data(using: String.Encoding.utf8)!

let byteArray = (data as NSData).bytes.assumingMemoryBound(to: Int8.self)
let length = Int(data.count)
var position = Int(0)

var decodedCoordinates = [CLLocationCoordinate2D]()
var decodedCoordinates = [LocationCoordinate2D]()

var lat = 0.0
var lon = 0.0
Expand All @@ -193,12 +199,13 @@ public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -
return nil
}

decodedCoordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lon))
decodedCoordinates.append(LocationCoordinate2D(latitude: lat, longitude: lon))
}

return decodedCoordinates
}

#if canImport(CoreLocation)
/// This function decodes a String to a [CLLocation]?
///
/// - parameter encodedPolyline: String representing the encoded Polyline
Expand All @@ -209,6 +216,7 @@ public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -

return decodePolyline(encodedPolyline, precision: precision).map(toLocations)
}
#endif

/// This function decodes a `String` to an `[UInt32]`
///
Expand Down Expand Up @@ -374,6 +382,7 @@ enum PolylineError: Error {
case chunkExtractingError
}

#if canImport(CoreLocation)
private func toCoordinates(_ locations: [CLLocation]) -> [CLLocationCoordinate2D] {
return locations.map {location in location.coordinate}
}
Expand All @@ -383,6 +392,7 @@ private func toLocations(_ coordinates: [CLLocationCoordinate2D]) -> [CLLocation
CLLocation(latitude:coordinate.latitude, longitude:coordinate.longitude)
}
}
#endif

private func isSeparator(_ value: Int32) -> Bool {
return (value - 63) & 0x20 != 0x20
Expand Down

0 comments on commit f0553ac

Please sign in to comment.