Skip to content

Commit 0f949fe

Browse files
committed
Availability macro support for back-deployed Span
1 parent 81fded4 commit 0f949fe

4 files changed

Lines changed: 83 additions & 66 deletions

File tree

Package.swift

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,63 +12,57 @@
1212

1313
import PackageDescription
1414

15-
struct Available {
15+
struct Availability {
1616
var name: String
1717
var version: String
1818
var osAvailability: String
19-
var sourceAvailability: String
2019

21-
init(
22-
_ version: String,
23-
_ osAvailability: String
24-
) {
25-
self.name = "System"
26-
self.version = version
27-
self.osAvailability = osAvailability
28-
self.sourceAvailability = "macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0"
20+
var minOSVersions: String {
21+
"macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0"
2922
}
30-
31-
var swiftSetting: SwiftSetting {
32-
#if SYSTEM_ABI_STABLE
33-
// Use availability matching Darwin API.
34-
let availability = self.osAvailability
35-
#else
36-
// Use availability matching SwiftPM default.
37-
let availability = self.sourceAvailability
38-
#endif
39-
return .enableExperimentalFeature(
40-
"AvailabilityMacro=\(self.name) \(version):\(availability)")
23+
var spanOSVersions: String {
24+
"macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0"
4125
}
42-
}
43-
44-
let availability: [Available] = [
45-
Available("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"),
46-
47-
Available("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"),
4826

49-
Available("0.0.3", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"),
50-
Available("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"),
51-
52-
Available("1.1.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"),
53-
Available("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"),
54-
55-
Available("1.2.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"),
56-
Available("1.3.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"),
57-
58-
Available("1.3.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"),
59-
Available("1.3.2", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"),
60-
Available("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"),
27+
var isStandardAvailability: Bool { name == "System" }
28+
}
6129

62-
Available("1.4.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
63-
Available("1.4.2", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
64-
Available("1.5.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
65-
Available("1.6.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
66-
Available("1.6.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
30+
let availabilityMap: [(String, String)] = [
31+
("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"),
32+
("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"),
33+
("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"),
34+
("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"),
35+
("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"),
6736

68-
Available("99", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
37+
("99", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
6938
]
7039

71-
let swiftSettingsAvailability = availability.map(\.swiftSetting)
40+
let availabilities: [Availability] =
41+
availabilityMap.map {
42+
Availability(name: "System", version: $0.0, osAvailability: $0.1)
43+
} + availabilityMap.prefix(5).map {
44+
Availability(name: "SystemWithSpan", version: $0.0, osAvailability: $0.1)
45+
}
46+
47+
let swiftSettingsAvailability = availabilities.map {
48+
availability -> SwiftSetting in
49+
let osVersionList: String
50+
#if SYSTEM_ABI_STABLE
51+
// Use availability matching Darwin API.
52+
availability = availability.osAvailability
53+
#else
54+
if availability.isStandardAvailability {
55+
// Use availability matching SwiftPM minimum.
56+
osVersionList = availability.minOSVersions
57+
} else {
58+
// Use availability matching Span deployment minimum.
59+
osVersionList = availability.spanOSVersions
60+
}
61+
#endif
62+
return .enableExperimentalFeature(
63+
"AvailabilityMacro=\(availability.name) \(availability.version):\(osVersionList)"
64+
)
65+
}
7266

7367
#if SYSTEM_CI
7468
let swiftSettingsCI: [SwiftSetting] = [

Sources/System/FileHelpers.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extension FileDescriptor {
2020
/// If `body` throws an error
2121
/// or an error occurs while closing the file descriptor,
2222
/// this method rethrows that error.
23+
@available(System 0.0.1, *)
2324
public func closeAfter<R>(_ body: () throws -> R) throws -> R {
2425
// No underscore helper, since the closure's throw isn't necessarily typed.
2526
let result: R
@@ -49,6 +50,7 @@ extension FileDescriptor {
4950
/// If `sequence` doesn't implement
5051
/// the <doc://com.apple.documentation/documentation/swift/sequence/3128824-withcontiguousstorageifavailable> method,
5152
/// temporary space will be allocated as needed.
53+
@available(System 0.0.1, *)
5254
@_alwaysEmitIntoClient
5355
@discardableResult
5456
public func writeAll<S: Sequence>(
@@ -98,6 +100,7 @@ extension FileDescriptor {
98100
/// If `sequence` doesn't implement
99101
/// the <doc://com.apple.documentation/documentation/swift/sequence/3128824-withcontiguousstorageifavailable> method,
100102
/// temporary space will be allocated as needed.
103+
@available(System 0.0.1, *)
101104
@_alwaysEmitIntoClient
102105
@discardableResult
103106
public func writeAll<S: Sequence>(
@@ -106,6 +109,7 @@ extension FileDescriptor {
106109
try _writeAll(toAbsoluteOffset: offset, sequence).get()
107110
}
108111

112+
@available(System 0.0.1, *)
109113
@usableFromInline
110114
internal func _writeAll<S: Sequence>(
111115
toAbsoluteOffset offset: Int64, _ sequence: S
@@ -115,6 +119,7 @@ extension FileDescriptor {
115119
}
116120
}
117121

122+
@available(System 0.0.1, *)
118123
@_alwaysEmitIntoClient
119124
internal func _writeAllBuffer(
120125
toAbsoluteOffset offset: Int64, _ buffer: UnsafeRawBufferPointer
@@ -134,6 +139,7 @@ extension FileDescriptor {
134139
return .success(buffer.count)
135140
}
136141

142+
#if compiler(>=6.2)
137143
/// Writes the entire contents of a buffer, retrying on partial writes.
138144
///
139145
/// - Parameters:
@@ -150,7 +156,7 @@ extension FileDescriptor {
150156
/// call the ``seek(offset:from:)`` method.
151157
///
152158
/// The corresponding C function is `write`.
153-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
159+
@available(SystemWithSpan 0.0.1, *)
154160
@_alwaysEmitIntoClient
155161
public func writeAll(
156162
_ data: RawSpan,
@@ -177,7 +183,7 @@ extension FileDescriptor {
177183
/// this method leaves the file's existing offset unchanged.
178184
///
179185
/// The corresponding C function is `pwrite`.
180-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
186+
@available(SystemWithSpan 0.0.1, *)
181187
@_alwaysEmitIntoClient
182188
public func writeAll(
183189
toAbsoluteOffset offset: Int64,
@@ -205,7 +211,7 @@ extension FileDescriptor {
205211
/// call the ``seek(offset:from:)`` method.
206212
///
207213
/// The corresponding C function is `read`.
208-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
214+
@available(SystemWithSpan 0.0.1, *)
209215
@_alwaysEmitIntoClient
210216
@discardableResult
211217
public func read(
@@ -238,7 +244,7 @@ extension FileDescriptor {
238244
/// this method leaves the file's existing offset unchanged.
239245
///
240246
/// The corresponding C function is `pread`.
241-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
247+
@available(SystemWithSpan 0.0.1, *)
242248
@_alwaysEmitIntoClient
243249
@discardableResult
244250
public func read(
@@ -257,4 +263,5 @@ extension FileDescriptor {
257263
}
258264
return originalCapacity - buffer.freeCapacity
259265
}
266+
#endif // swift(>=6.2)
260267
}

Sources/System/FileOperations.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extension FileDescriptor {
2323
/// - Returns: A file descriptor for the open file
2424
///
2525
/// The corresponding C function is `open`.
26+
@available(System 0.0.1, *)
2627
@_alwaysEmitIntoClient
2728
public static func open(
2829
_ path: FilePath,
@@ -62,6 +63,7 @@ extension FileDescriptor {
6263
/// - Returns: A file descriptor for the open file
6364
///
6465
/// The corresponding C function is `open`.
66+
@available(System 0.0.1, *)
6567
@_alwaysEmitIntoClient
6668
public static func open(
6769
_ path: UnsafePointer<CChar>,
@@ -75,6 +77,7 @@ extension FileDescriptor {
7577
).get()
7678
}
7779

80+
@available(System 0.0.1, *)
7881
@usableFromInline
7982
internal static func _open(
8083
_ path: UnsafePointer<CChar>,
@@ -148,6 +151,7 @@ extension FileDescriptor {
148151
/// the object will be deactivated.
149152
///
150153
/// The corresponding C function is `close`.
154+
@available(System 0.0.1, *)
151155
@_alwaysEmitIntoClient
152156
public func close() throws { try _close().get() }
153157

@@ -165,6 +169,7 @@ extension FileDescriptor {
165169
/// in bytes from the beginning of the file.
166170
///
167171
/// The corresponding C function is `lseek`.
172+
@available(System 0.0.1, *)
168173
@_alwaysEmitIntoClient
169174
@discardableResult
170175
public func seek(
@@ -173,6 +178,7 @@ extension FileDescriptor {
173178
try _seek(offset: offset, from: whence).get()
174179
}
175180

181+
@available(System 0.0.1, *)
176182
@usableFromInline
177183
internal func _seek(
178184
offset: Int64, from whence: FileDescriptor.SeekOrigin
@@ -210,6 +216,7 @@ extension FileDescriptor {
210216
/// call the ``seek(offset:from:)`` method.
211217
///
212218
/// The corresponding C function is `read`.
219+
@available(System 0.0.1, *)
213220
@_alwaysEmitIntoClient
214221
public func read(
215222
into buffer: UnsafeMutableRawBufferPointer,
@@ -218,6 +225,7 @@ extension FileDescriptor {
218225
try _read(into: buffer, retryOnInterrupt: retryOnInterrupt).get()
219226
}
220227

228+
@available(System 0.0.1, *)
221229
@usableFromInline
222230
internal func _read(
223231
into buffer: UnsafeMutableRawBufferPointer,
@@ -246,6 +254,7 @@ extension FileDescriptor {
246254
/// this method leaves the file's existing offset unchanged.
247255
///
248256
/// The corresponding C function is `pread`.
257+
@available(System 0.0.1, *)
249258
@_alwaysEmitIntoClient
250259
public func read(
251260
fromAbsoluteOffset offset: Int64,
@@ -259,6 +268,7 @@ extension FileDescriptor {
259268
).get()
260269
}
261270

271+
@available(System 0.0.1, *)
262272
@usableFromInline
263273
internal func _read(
264274
fromAbsoluteOffset offset: Int64,
@@ -299,6 +309,7 @@ extension FileDescriptor {
299309
/// call the ``seek(offset:from:)`` method.
300310
///
301311
/// The corresponding C function is `write`.
312+
@available(System 0.0.1, *)
302313
@_alwaysEmitIntoClient
303314
public func write(
304315
_ buffer: UnsafeRawBufferPointer,
@@ -307,6 +318,7 @@ extension FileDescriptor {
307318
try _write(buffer, retryOnInterrupt: retryOnInterrupt).get()
308319
}
309320

321+
@available(System 0.0.1, *)
310322
@usableFromInline
311323
internal func _write(
312324
_ buffer: UnsafeRawBufferPointer,
@@ -332,6 +344,7 @@ extension FileDescriptor {
332344
/// this method leaves the file's existing offset unchanged.
333345
///
334346
/// The corresponding C function is `pwrite`.
347+
@available(System 0.0.1, *)
335348
@_alwaysEmitIntoClient
336349
public func write(
337350
toAbsoluteOffset offset: Int64,
@@ -341,6 +354,7 @@ extension FileDescriptor {
341354
try _write(toAbsoluteOffset: offset, buffer, retryOnInterrupt: retryOnInterrupt).get()
342355
}
343356

357+
@available(System 0.0.1, *)
344358
@usableFromInline
345359
internal func _write(
346360
toAbsoluteOffset offset: Int64,
@@ -366,6 +380,7 @@ extension FileDescriptor {
366380
retryOnInterrupt: retryOnInterrupt)
367381
}
368382

383+
#if compiler(>=6.2)
369384
/// Writes the contents of a buffer at the current file offset.
370385
///
371386
/// - Parameters:
@@ -382,7 +397,7 @@ extension FileDescriptor {
382397
/// call the ``seek(offset:from:)`` method.
383398
///
384399
/// The corresponding C function is `write`.
385-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
400+
@available(SystemWithSpan 0.0.1, *)
386401
@_alwaysEmitIntoClient
387402
public func write(
388403
_ data: RawSpan,
@@ -408,7 +423,7 @@ extension FileDescriptor {
408423
/// this method leaves the file's existing offset unchanged.
409424
///
410425
/// The corresponding C function is `pwrite`.
411-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
426+
@available(SystemWithSpan 0.0.1, *)
412427
@_alwaysEmitIntoClient
413428
public func write(
414429
toAbsoluteOffset offset: Int64,
@@ -420,7 +435,7 @@ extension FileDescriptor {
420435
}
421436
}
422437

423-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
438+
@available(SystemWithSpan 0.0.1, *)
424439
@_alwaysEmitIntoClient
425440
internal func _readIntoOutputBuffer(
426441
_ buffer: UnsafeMutableRawBufferPointer,
@@ -459,7 +474,7 @@ extension FileDescriptor {
459474
/// call the ``seek(offset:from:)`` method.
460475
///
461476
/// The corresponding C function is `read`.
462-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
477+
@available(SystemWithSpan 0.0.1, *)
463478
@_alwaysEmitIntoClient
464479
public func read(
465480
into buffer: inout OutputRawSpan,
@@ -485,7 +500,7 @@ extension FileDescriptor {
485500
/// this method leaves the file's existing offset unchanged.
486501
///
487502
/// The corresponding C function is `pread`.
488-
@available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *)
503+
@available(SystemWithSpan 0.0.1, *)
489504
@_alwaysEmitIntoClient
490505
public func read(
491506
fromAbsoluteOffset offset: Int64,
@@ -509,6 +524,7 @@ extension FileDescriptor {
509524
fatalError("Unexpected error type")
510525
}
511526
}
527+
#endif // compiler(>=6.2)
512528
}
513529

514530
#if !os(WASI)

0 commit comments

Comments
 (0)