Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Move platform requirements to availability annotations #348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
// swift-tools-version: 5.8

import PackageDescription
import CompilerPluginSupport

// Availability Macros
let availabilityTags = [Availability("AsyncAlgorithms")]
let versionNumbers = ["1.0"]

// Availability Macro Utilities
enum OSAvailability: String {
// This should match the package's deployment target
case initialIntroduction = "macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0"
case pending = "macOS 9999, iOS 9999, tvOS 9999, watchOS 9999"
// Use 10000 for future availability to avoid compiler magic around
// the 9999 version number but ensure it is greater than 9999
case future = "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be good to have a "pending" case for the 9999 versions

}

struct Availability {
let name: String
let osAvailability: OSAvailability

init(_ name: String, availability: OSAvailability = .initialIntroduction) {
self.name = name
self.osAvailability = availability
}
}

let availabilityMacros: [SwiftSetting] = versionNumbers.flatMap { version in
availabilityTags.map {
.enableExperimentalFeature("AvailabilityMacro=\($0.name) \(version):\($0.osAvailability.rawValue)")
}
}

let package = Package(
name: "swift-async-algorithms",
platforms: [
.macOS("10.15"),
.iOS("13.0"),
.tvOS("13.0"),
.watchOS("6.0"),
],
products: [
.library(name: "AsyncAlgorithms", targets: ["AsyncAlgorithms"])
],
Expand All @@ -20,29 +45,29 @@ let package = Package(
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "DequeModule", package: "swift-collections"),
],
swiftSettings: [
swiftSettings: availabilityMacros + [
.enableExperimentalFeature("StrictConcurrency=complete")
]
),
.target(
name: "AsyncSequenceValidation",
dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"],
swiftSettings: [
swiftSettings: availabilityMacros + [
.enableExperimentalFeature("StrictConcurrency=complete")
]
),
.systemLibrary(name: "_CAsyncSequenceValidationSupport"),
.target(
name: "AsyncAlgorithms_XCTest",
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"],
swiftSettings: [
swiftSettings: availabilityMacros + [
.enableExperimentalFeature("StrictConcurrency=complete")
]
),
.testTarget(
name: "AsyncAlgorithmsTests",
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"],
swiftSettings: [
swiftSettings: availabilityMacros + [
.enableExperimentalFeature("StrictConcurrency=complete")
]
),
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncAlgorithms/AsyncAdjacentPairsSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//
//===----------------------------------------------------------------------===//

@available(AsyncAlgorithms 1.0, *)
extension AsyncSequence {
/// An `AsyncSequence` that iterates over the adjacent pairs of the original
/// original `AsyncSequence`.
Expand All @@ -26,6 +27,7 @@ extension AsyncSequence {
///
/// - Returns: An `AsyncSequence` where the element is a tuple of two adjacent elements
/// or the original `AsyncSequence`.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func adjacentPairs() -> AsyncAdjacentPairsSequence<Self> {
AsyncAdjacentPairsSequence(self)
Expand All @@ -34,6 +36,7 @@ extension AsyncSequence {

/// An `AsyncSequence` that iterates over the adjacent pairs of the original
/// `AsyncSequence`.
@available(AsyncAlgorithms 1.0, *)
@frozen
public struct AsyncAdjacentPairsSequence<Base: AsyncSequence>: AsyncSequence {
public typealias Element = (Base.Element, Base.Element)
Expand Down Expand Up @@ -83,6 +86,7 @@ public struct AsyncAdjacentPairsSequence<Base: AsyncSequence>: AsyncSequence {
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncAdjacentPairsSequence: Sendable where Base: Sendable, Base.Element: Sendable {}

@available(*, unavailable)
Expand Down
2 changes: 2 additions & 0 deletions Sources/AsyncAlgorithms/AsyncBufferedByteIterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
/// }
///
///
@available(AsyncAlgorithms 1.0, *)
public struct AsyncBufferedByteIterator: AsyncIteratorProtocol {
public typealias Element = UInt8
@usableFromInline var buffer: _AsyncBytesBuffer
Expand Down Expand Up @@ -67,6 +68,7 @@ public struct AsyncBufferedByteIterator: AsyncIteratorProtocol {
@available(*, unavailable)
extension AsyncBufferedByteIterator: Sendable {}

@available(AsyncAlgorithms 1.0, *)
@frozen @usableFromInline
internal struct _AsyncBytesBuffer {
@usableFromInline
Expand Down
6 changes: 6 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChain2Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/// - s2: The second asynchronous sequence.
/// - Returns: An asynchronous sequence that iterates first over the elements of `s1`, and
/// then over the elements of `s2`.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chain<Base1: AsyncSequence, Base2: AsyncSequence>(
_ s1: Base1,
Expand All @@ -26,6 +27,7 @@ public func chain<Base1: AsyncSequence, Base2: AsyncSequence>(
}

/// A concatenation of two asynchronous sequences with the same element type.
@available(AsyncAlgorithms 1.0, *)
@frozen
public struct AsyncChain2Sequence<Base1: AsyncSequence, Base2: AsyncSequence> where Base1.Element == Base2.Element {
@usableFromInline
Expand All @@ -41,10 +43,12 @@ public struct AsyncChain2Sequence<Base1: AsyncSequence, Base2: AsyncSequence> wh
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChain2Sequence: AsyncSequence {
public typealias Element = Base1.Element

/// The iterator for a `AsyncChain2Sequence` instance.
@available(AsyncAlgorithms 1.0, *)
@frozen
public struct Iterator: AsyncIteratorProtocol {
@usableFromInline
Expand Down Expand Up @@ -76,12 +80,14 @@ extension AsyncChain2Sequence: AsyncSequence {
}
}

@available(AsyncAlgorithms 1.0, *)
@inlinable
public func makeAsyncIterator() -> Iterator {
Iterator(base1.makeAsyncIterator(), base2.makeAsyncIterator())
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChain2Sequence: Sendable where Base1: Sendable, Base2: Sendable {}

@available(*, unavailable)
Expand Down
6 changes: 6 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChain3Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/// - s3: The third asynchronous sequence.
/// - Returns: An asynchronous sequence that iterates first over the elements of `s1`, and
/// then over the elements of `s2`, and then over the elements of `s3`
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chain<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequence>(
_ s1: Base1,
Expand All @@ -28,6 +29,7 @@ public func chain<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequen
}

/// A concatenation of three asynchronous sequences with the same element type.
@available(AsyncAlgorithms 1.0, *)
@frozen
public struct AsyncChain3Sequence<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequence>
where Base1.Element == Base2.Element, Base1.Element == Base3.Element {
Expand All @@ -48,10 +50,12 @@ where Base1.Element == Base2.Element, Base1.Element == Base3.Element {
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChain3Sequence: AsyncSequence {
public typealias Element = Base1.Element

/// The iterator for a `AsyncChain3Sequence` instance.
@available(AsyncAlgorithms 1.0, *)
@frozen
public struct Iterator: AsyncIteratorProtocol {
@usableFromInline
Expand Down Expand Up @@ -93,12 +97,14 @@ extension AsyncChain3Sequence: AsyncSequence {
}
}

@available(AsyncAlgorithms 1.0, *)
@inlinable
public func makeAsyncIterator() -> Iterator {
Iterator(base1.makeAsyncIterator(), base2.makeAsyncIterator(), base3.makeAsyncIterator())
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChain3Sequence: Sendable where Base1: Sendable, Base2: Sendable, Base3: Sendable {}

@available(*, unavailable)
Expand Down
5 changes: 5 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChunkedByGroupSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
//
//===----------------------------------------------------------------------===//

@available(AsyncAlgorithms 1.0, *)
extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection`
/// type by testing if elements belong in the same group.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunked<Collected: RangeReplaceableCollection>(
into: Collected.Type,
Expand All @@ -21,6 +23,7 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks by testing if elements belong in the same group.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunked(
by belongInSameGroup: @escaping @Sendable (Element, Element) -> Bool
Expand Down Expand Up @@ -51,6 +54,7 @@ extension AsyncSequence {
/// // [10, 20, 30]
/// // [10, 40, 40]
/// // [10, 20]
@available(AsyncAlgorithms 1.0, *)
public struct AsyncChunkedByGroupSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence
where Collected.Element == Base.Element {
public typealias Element = Collected
Expand Down Expand Up @@ -121,6 +125,7 @@ where Collected.Element == Base.Element {
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChunkedByGroupSequence: Sendable where Base: Sendable, Base.Element: Sendable {}

@available(*, unavailable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
//
//===----------------------------------------------------------------------===//

@available(AsyncAlgorithms 1.0, *)
extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type on the uniqueness of a given subject.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunked<Subject: Equatable, Collected: RangeReplaceableCollection>(
into: Collected.Type,
Expand All @@ -20,6 +22,7 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks on the uniqueness of a given subject.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunked<Subject: Equatable>(
on projection: @escaping @Sendable (Element) -> Subject
Expand All @@ -29,6 +32,7 @@ extension AsyncSequence {
}

/// An `AsyncSequence` that chunks on a subject when it differs from the last element.
@available(AsyncAlgorithms 1.0, *)
public struct AsyncChunkedOnProjectionSequence<
Base: AsyncSequence,
Subject: Equatable,
Expand Down Expand Up @@ -104,6 +108,7 @@ public struct AsyncChunkedOnProjectionSequence<
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChunkedOnProjectionSequence: Sendable where Base: Sendable, Base.Element: Sendable {}

@available(*, unavailable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
//
//===----------------------------------------------------------------------===//

@available(AsyncAlgorithms 1.0, *)
extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type of a given count or when a signal `AsyncSequence` produces an element.
@available(AsyncAlgorithms 1.0, *)
public func chunks<Signal, Collected: RangeReplaceableCollection>(
ofCount count: Int,
or signal: Signal,
Expand All @@ -20,6 +22,7 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks of a given count or when a signal `AsyncSequence` produces an element.
@available(AsyncAlgorithms 1.0, *)
public func chunks<Signal>(
ofCount count: Int,
or signal: Signal
Expand All @@ -28,6 +31,7 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type when a signal `AsyncSequence` produces an element.
@available(AsyncAlgorithms 1.0, *)
public func chunked<Signal, Collected: RangeReplaceableCollection>(
by signal: Signal,
into: Collected.Type
Expand All @@ -36,6 +40,7 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks when a signal `AsyncSequence` produces an element.
@available(AsyncAlgorithms 1.0, *)
public func chunked<Signal>(by signal: Signal) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], Signal> {
chunked(by: signal, into: [Element].self)
}
Expand Down Expand Up @@ -78,6 +83,7 @@ extension AsyncSequence {
}

/// An `AsyncSequence` that chunks elements into collected `RangeReplaceableCollection` instances by either count or a signal from another `AsyncSequence`.
@available(AsyncAlgorithms 1.0, *)
public struct AsyncChunksOfCountOrSignalSequence<
Base: AsyncSequence,
Collected: RangeReplaceableCollection,
Expand Down
9 changes: 6 additions & 3 deletions Sources/AsyncAlgorithms/AsyncChunksOfCountSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
//
//===----------------------------------------------------------------------===//

@available(AsyncAlgorithms 1.0, *)
extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` of a given count.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunks<Collected: RangeReplaceableCollection>(
ofCount count: Int,
Expand All @@ -20,13 +22,15 @@ extension AsyncSequence {
}

/// Creates an asynchronous sequence that creates chunks of a given count.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func chunks(ofCount count: Int) -> AsyncChunksOfCountSequence<Self, [Element]> {
chunks(ofCount: count, into: [Element].self)
}
}

/// An `AsyncSequence` that chunks elements into `RangeReplaceableCollection` instances of at least a given count.
@available(AsyncAlgorithms 1.0, *)
public struct AsyncChunksOfCountSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence
where Collected.Element == Base.Element {
public typealias Element = Collected
Expand Down Expand Up @@ -89,8 +93,7 @@ where Collected.Element == Base.Element {
}
}

@available(AsyncAlgorithms 1.0, *)
extension AsyncChunksOfCountSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
@available(AsyncAlgorithms 1.0, *)
extension AsyncChunksOfCountSequence.Iterator: Sendable where Base.AsyncIterator: Sendable, Base.Element: Sendable {}

@available(*, unavailable)
extension AsyncChunksOfCountSequence.Iterator: Sendable {}
Loading
Loading