Skip to content

Commit

Permalink
Add support for Sendable
Browse files Browse the repository at this point in the history
  • Loading branch information
S2Ler committed Jun 19, 2023
1 parent e17995b commit de98d12
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 28 deletions.
62 changes: 62 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
version: 2.1

jobs:
xcode_13_2:
macos:
xcode: 13.2
steps:
- checkout
- run:
name: "Build"
command: "swift build"
xcode_13_3:
macos:
xcode: 13.3
steps:
- checkout
- run:
name: "Build"
command: "swift build"
xcode_13_4:
macos:
xcode: 13.4
steps:
- checkout
- run:
name: "Build"
command: "swift build"
- run:
name: "Test"
command: "swift test"
xcode_14_1:
macos:
xcode: 14.1
steps:
- checkout
- run:
name: "Build"
command: "swift build"
- run:
name: "Test"
command: "swift test"
xcode_14_2:
macos:
xcode: 14.2
steps:
- checkout
- run:
name: "Build"
command: "swift build"
- run:
name: "Test"
command: "swift test"


workflows:
build-and-test:
jobs:
- xcode_13_2
- xcode_13_3
- xcode_13_4
- xcode_14_1
- xcode_14_2
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ language: generic
sudo: required
dist: xenial
env:
- SWIFT_VERSION=5.4 SWIFTENV_ROOT="$HOME/.swiftenv" PATH="$SWIFTENV_ROOT/bin:$SWIFTENV_ROOT/shims:$PATH"
- SWIFT_VERSION=5.5 SWIFTENV_ROOT="$HOME/.swiftenv" PATH="$SWIFTENV_ROOT/bin:$SWIFTENV_ROOT/shims:$PATH"
install:
- ./scripts/install_swiftenv.sh
script:
Expand Down
13 changes: 12 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.4
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down Expand Up @@ -36,3 +36,14 @@ let package = Package(
),
]
)

//for target in package.targets {
// target.swiftSettings = target.swiftSettings ?? []
// target.swiftSettings?.append(
// .unsafeFlags([
// "-Xfrontend", "-warn-concurrency",
// "-Xfrontend", "-enable-actor-data-race-checks",
// "-Xfrontend", "-require-explicit-sendable",
// ])
// )
//}
2 changes: 1 addition & 1 deletion Sources/Turf/BoundingBox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CoreLocation
/**
A [bounding box](https://datatracker.ietf.org/doc/html/rfc7946#section-5) indicates the extremes of a `GeoJSONObject` along the x- and y-axes (longitude and latitude, respectively).
*/
public struct BoundingBox {
public struct BoundingBox: Sendable {
/// The southwesternmost position contained in the bounding box.
public var southWest: LocationCoordinate2D

Expand Down
10 changes: 5 additions & 5 deletions Sources/Turf/Consumer/Consumer+WKT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import CoreLocation
struct WKTParser {
init() {}

mutating func parse<T>(_ input: String) throws -> T {
mutating func parse<T: Sendable>(_ input: String) throws -> T {
let match = try wktConsumer.match(input.uppercased())
guard let output = try match.transform(wktTransform) else {
throw WKTError.emptyOutput
Expand All @@ -21,16 +21,16 @@ struct WKTParser {
return object
}

static func parse<T>(_ input: String) throws -> T {
static func parse<T: Sendable>(_ input: String) throws -> T {
var parser = WKTParser()
return try parser.parse(input)
}

enum WKTError: Error, CustomStringConvertible {
case emptyOutput
case numberParsingFailed(Any)
case coordinatesParsingFailed(Any)
case geometriesParsingFailed(Any)
case numberParsingFailed(Sendable)
case coordinatesParsingFailed(Sendable)
case geometriesParsingFailed(Sendable)
case castFailed(Any.Type)

public var description: String {
Expand Down
20 changes: 12 additions & 8 deletions Sources/Turf/Consumer/Consumer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Foundation

// MARK: Consumer

public indirect enum Consumer<Label: Hashable>: Equatable {
public indirect enum Consumer<Label: Hashable & Sendable>: Equatable, Sendable {
/// Primitives
case string(String)
case charset(Charset)
Expand Down Expand Up @@ -67,38 +67,38 @@ public extension Consumer {
var isOptional: Bool { return _isOptional }

/// Source location
struct Location: Equatable {
struct Location: Equatable, Sendable {
fileprivate var source: String.UnicodeScalarView
public let range: Range<String.Index>
public var offset: (line: Int, column: Int) { return _offset }
}

/// Abstract syntax tree returned by consumer
indirect enum Match: Equatable {
indirect enum Match: Equatable, Sendable {
case token(String, Location)
case node(Label?, [Match])

/// The location of the match in the original source (if known)
public var location: Location? { return _location }

/// Transform generic AST to application-specific form
public func transform(_ fn: Transform) rethrows -> Any? {
public func transform(_ fn: Transform) rethrows -> Sendable? {
return try _transform(fn)
}
}

/// Opaque type used for efficient character matching
struct Charset: Hashable {
struct Charset: Hashable, Sendable {
fileprivate let characterSet: CharacterSet
let inverted: Bool
}

/// Closure for transforming a Match to an application-specific data type
typealias Transform = (_ name: Label, _ values: [Any]) throws -> Any?
typealias Transform = (_ name: Label, _ values: [Sendable]) throws -> (Sendable)?

/// A Parsing error
struct Error: Swift.Error {
public indirect enum Kind {
public indirect enum Kind: Sendable {
case expected(Consumer)
case unexpectedToken
case custom(Swift.Error)
Expand Down Expand Up @@ -784,7 +784,7 @@ private extension Consumer.Match {
}
}

func _transform(_ fn: Consumer.Transform) rethrows -> Any? {
func _transform(_ fn: Consumer.Transform) rethrows -> Sendable? {
// TODO: warn if no matches are labelled, as transform won't work
do {
switch self {
Expand Down Expand Up @@ -885,3 +885,7 @@ private func escapeString<T: StringProtocol>(_ string: T) -> String {
}
return result + "'"
}

#if swift(<5.6)
extension CharacterSet: @unchecked Sendable {}
#endif
2 changes: 1 addition & 1 deletion Sources/Turf/CoreLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public typealias LocationDegrees = Double
/**
A geographic coordinate with its components measured in degrees.
*/
public struct LocationCoordinate2D {
public struct LocationCoordinate2D: Sendable {
/**
The latitude in degrees.
*/
Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/FeatureIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
/**
A [feature identifier](https://datatracker.ietf.org/doc/html/rfc7946#section-3.2) identifies a `Feature` object.
*/
public enum FeatureIdentifier: Hashable {
public enum FeatureIdentifier: Hashable, Sendable {
/// A string.
case string(_ string: String)

Expand Down
4 changes: 2 additions & 2 deletions Sources/Turf/GeoJSON.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import CoreLocation

- Note: [Foreign members](https://datatracker.ietf.org/doc/html/rfc7946#section-6.1) which may be present inside are coded only if used `JSONEncoder` or `JSONDecoder` has `userInfo[.includesForeignMembers] = true`.
*/
public enum GeoJSONObject: Equatable {
public enum GeoJSONObject: Equatable, Sendable {
/**
A [Geometry object](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1) represents points, curves, and surfaces in coordinate space.

Expand Down Expand Up @@ -94,7 +94,7 @@ extension FeatureCollection: GeoJSONObjectConvertible {
/**
A GeoJSON object that can contain [foreign members](https://datatracker.ietf.org/doc/html/rfc7946#section-6.1) in arbitrary keys.
*/
public protocol ForeignMemberContainer {
public protocol ForeignMemberContainer: Sendable {
/// [Foreign members](https://datatracker.ietf.org/doc/html/rfc7946#section-6.1) to round-trip to JSON.
///
/// Members are coded only if used `JSONEncoder` or `JSONDecoder` has `userInfo[.includesForeignMembers] = true`.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/Geometries/GeometryCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CoreLocation
/**
A [GeometryCollection geometry](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.8) is a heterogeneous collection of `Geometry` objects that are related.
*/
public struct GeometryCollection: Equatable, ForeignMemberContainer {
public struct GeometryCollection: Equatable, ForeignMemberContainer, Sendable {
/// The geometries contained by the geometry collection.
public var geometries: [Geometry]

Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/Geometries/LineString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ extension LineString {
/**
`IndexedCoordinate` is a coordinate with additional information such as the index from its position in the polyline and distance from the start of the polyline.
*/
public struct IndexedCoordinate {
public struct IndexedCoordinate: Sendable {
/// The coordinate
public let coordinate: Array<LocationCoordinate2D>.Element
/// The index of the coordinate
Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/Geometries/Point.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CoreLocation
/**
A [Point geometry](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.2) represents a single position.
*/
public struct Point: Equatable, ForeignMemberContainer {
public struct Point: Equatable, ForeignMemberContainer, Sendable {
/**
The position at which the point is located.

Expand Down
4 changes: 2 additions & 2 deletions Sources/Turf/Geometry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CoreLocation
/**
A [Geometry object](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1) represents points, curves, and surfaces in coordinate space. Use an instance of this enumeration whenever a value could be any kind of Geometry object.
*/
public enum Geometry: Equatable {
public enum Geometry: Equatable, Sendable {
/// A single position.
case point(_ geometry: Point)

Expand Down Expand Up @@ -94,7 +94,7 @@ extension Geometry: Codable {
/**
A type that can be represented as a `Geometry` instance.
*/
public protocol GeometryConvertible {
public protocol GeometryConvertible: Sendable {
/// The instance wrapped in a `Geometry` instance.
var geometry: Geometry { get }
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/JSON.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation

This type does not represent the `null` value in JSON. Use `Optional<JSONValue>` wherever `null` is accepted.
*/
public enum JSONValue: Hashable {
public enum JSONValue: Hashable, Sendable {
// case null would be redundant to Optional.none

/// A string.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Turf/RadianCoordinate2D.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public typealias RadianDistance = Double
/**
A coordinate pair measured in radians, as opposed to `LocationCoordinate2D`, which is measured in degrees of arc.
*/
public struct RadianCoordinate2D {
public struct RadianCoordinate2D: Sendable {
/// The latitude measured in radians.
private(set) var latitude: LocationRadians

Expand Down
3 changes: 2 additions & 1 deletion Sources/Turf/Ring.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import CoreLocation
/**
A [linear ring](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6) is a closed figure bounded by three or more straight line segments.
*/
public struct Ring {

public struct Ring: Sendable {
/// The positions at which the linear ring is located.
public var coordinates: [LocationCoordinate2D]

Expand Down

0 comments on commit de98d12

Please sign in to comment.