Skip to content

Commit 4e8362c

Browse files
authored
Merge pull request #1520 from swiftlang/revert-1500-jgrynspan/adopt-span
Revert "Adopt `Span`/`RawSpan` almost everywhere."
2 parents 33e3787 + 96f6fd0 commit 4e8362c

18 files changed

Lines changed: 171 additions & 145 deletions

Sources/Testing/ABI/ABI.Record+Streaming.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ private import Foundation
1414
extension ABI.Version {
1515
static func eventHandler(
1616
encodeAsJSONLines: Bool,
17-
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: borrowing RawSpan) -> Void
17+
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void
1818
) -> Event.Handler {
1919
// Encode as JSON Lines if requested.
2020
var eventHandlerCopy = eventHandler
@@ -44,7 +44,7 @@ extension ABI.Version {
4444
extension ABI.Xcode16 {
4545
static func eventHandler(
4646
encodeAsJSONLines: Bool,
47-
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: borrowing RawSpan) -> Void
47+
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void
4848
) -> Event.Handler {
4949
return { event, context in
5050
if case .testDiscovered = event.kind {
@@ -63,7 +63,9 @@ extension ABI.Xcode16 {
6363
eventContext: Event.Context.Snapshot(snapshotting: context)
6464
)
6565
try? JSON.withEncoding(of: snapshot) { eventAndContextJSON in
66-
eventHandler(eventAndContextJSON)
66+
eventAndContextJSON.withUnsafeBytes { eventAndContextJSON in
67+
eventHandler(eventAndContextJSON)
68+
}
6769
}
6870
}
6971
}

Sources/Testing/ABI/ABI.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extension ABI {
3737
/// associated context is created and is passed to `eventHandler`.
3838
static func eventHandler(
3939
encodeAsJSONLines: Bool,
40-
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: borrowing RawSpan) -> Void
40+
forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void
4141
) -> Event.Handler
4242
#endif
4343
}

Sources/Testing/ABI/EntryPoints/ABIEntryPoint.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,9 @@ extension ABI.v0 {
4848
public static var entryPoint: EntryPoint {
4949
return { configurationJSON, recordHandler in
5050
let args = try configurationJSON.map { configurationJSON in
51-
try JSON.decode(__CommandLineArguments_v0.self, from: configurationJSON.bytes)
52-
}
53-
let eventHandler = try eventHandlerForStreamingEvents(withVersionNumber: args?.eventStreamVersionNumber, encodeAsJSONLines: false) { recordJSON in
54-
recordJSON.withUnsafeBytes(recordHandler)
51+
try JSON.decode(__CommandLineArguments_v0.self, from: configurationJSON)
5552
}
53+
let eventHandler = try eventHandlerForStreamingEvents(withVersionNumber: args?.eventStreamVersionNumber, encodeAsJSONLines: false, forwardingTo: recordHandler)
5654

5755
switch await Testing.entryPoint(passing: args, eventHandler: eventHandler) {
5856
case EXIT_SUCCESS, EXIT_NO_TESTS_FOUND:

Sources/Testing/ABI/EntryPoints/EntryPoint.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,9 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
425425
if let path = args.argumentValue(forLabel: "--configuration-path") ?? args.argumentValue(forLabel: "--experimental-configuration-path") {
426426
let file = try FileHandle(forReadingAtPath: path)
427427
let configurationJSON = try file.readToEnd()
428-
result = try JSON.decode(__CommandLineArguments_v0.self, from: configurationJSON.span.bytes)
428+
result = try configurationJSON.withUnsafeBufferPointer { configurationJSON in
429+
try JSON.decode(__CommandLineArguments_v0.self, from: .init(configurationJSON))
430+
}
429431

430432
// NOTE: We don't return early or block other arguments here: a caller is
431433
// allowed to pass a configuration AND e.g. "--verbose" and they'll both be
@@ -704,7 +706,7 @@ public func configurationForEntryPoint(from args: __CommandLineArguments_v0) thr
704706
func eventHandlerForStreamingEvents(
705707
withVersionNumber versionNumber: VersionNumber?,
706708
encodeAsJSONLines: Bool,
707-
forwardingTo targetEventHandler: @escaping @Sendable (borrowing RawSpan) -> Void
709+
forwardingTo targetEventHandler: @escaping @Sendable (UnsafeRawBufferPointer) -> Void
708710
) throws -> Event.Handler {
709711
let versionNumber = versionNumber ?? ABI.CurrentVersion.versionNumber
710712
guard let abi = ABI.version(forVersionNumber: versionNumber) else {

Sources/Testing/Attachments/Attachment.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ extension Attachment where AttachableValue: ~Copyable {
467467
// There should be no code path that leads to this call where the attachable
468468
// value is nil.
469469
try withUnsafeBytes { buffer in
470-
try file!.write(buffer.bytes)
470+
try file!.write(buffer)
471471
}
472472

473473
return result

Sources/Testing/Events/Event+FallbackHandler.swift

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,9 @@ private import _TestingInternals
1212

1313
extension Event {
1414
#if compiler(>=6.3) && !SWT_NO_INTEROP
15-
/// The installed fallback event handler.
1615
private static let _fallbackEventHandler: SWTFallbackEventHandler? = {
1716
_swift_testing_getFallbackEventHandler()
1817
}()
19-
20-
/// Encode an event and pass it to the installed fallback event handler.
21-
private static let _encodeAndInvoke: Event.Handler? = { [fallbackEventHandler = _fallbackEventHandler] in
22-
guard let fallbackEventHandler else {
23-
return nil
24-
}
25-
return ABI.CurrentVersion.eventHandler(encodeAsJSONLines: false) { recordJSON in
26-
recordJSON.withUnsafeBytes { recordJSON in
27-
fallbackEventHandler(
28-
String(describing: ABI.CurrentVersion.versionNumber),
29-
recordJSON.baseAddress!,
30-
recordJSON.count,
31-
nil
32-
)
33-
}
34-
}
35-
}()
3618
#endif
3719

3820
/// Post this event to the currently-installed fallback event handler.
@@ -45,12 +27,23 @@ extension Event {
4527
/// `false`.
4628
borrowing func postToFallbackHandler(in context: borrowing Context) -> Bool {
4729
#if compiler(>=6.3) && !SWT_NO_INTEROP
30+
guard let fallbackEventHandler = Self._fallbackEventHandler else {
31+
return false
32+
}
33+
4834
// Encode the event as JSON and pass it to the handler.
49-
if let encodeAndInvoke = Self._encodeAndInvoke {
50-
encodeAndInvoke(self, context)
51-
return true
35+
let encodeAndInvoke = ABI.CurrentVersion.eventHandler(encodeAsJSONLines: false) { recordJSON in
36+
fallbackEventHandler(
37+
String(describing: ABI.CurrentVersion.versionNumber),
38+
recordJSON.baseAddress!,
39+
recordJSON.count,
40+
nil
41+
)
5242
}
53-
#endif
43+
encodeAndInvoke(self, context)
44+
return true
45+
#else
5446
return false
47+
#endif
5548
}
5649
}

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,8 @@ extension ExitTest {
605605
/// and standard error streams of the current process.
606606
private static func _writeBarrierValues() {
607607
let barrierValue = Self.barrierValue
608-
try? FileHandle.stdout.write(barrierValue.span.bytes)
609-
try? FileHandle.stderr.write(barrierValue.span.bytes)
608+
try? FileHandle.stdout.write(barrierValue)
609+
try? FileHandle.stderr.write(barrierValue)
610610
}
611611

612612
/// A handler that is invoked when an exit test starts.
@@ -712,11 +712,13 @@ extension ExitTest {
712712

713713
/// The ID of the exit test to run, if any, specified in the environment.
714714
static var environmentIDForEntryPoint: ID? {
715-
guard let idString = Environment.variable(named: Self._idEnvironmentVariableName) else {
715+
guard var idString = Environment.variable(named: Self._idEnvironmentVariableName) else {
716716
return nil
717717
}
718718

719-
return try? JSON.decode(ExitTest.ID.self, from: idString.utf8.span.bytes)
719+
return try? idString.withUTF8 { idBuffer in
720+
try JSON.decode(ExitTest.ID.self, from: UnsafeRawBufferPointer(idBuffer))
721+
}
720722
}
721723

722724
/// Find the exit test function specified in the environment of the current
@@ -868,7 +870,7 @@ extension ExitTest {
868870
// Insert a specific variable that tells the child process which exit test
869871
// to run.
870872
try JSON.withEncoding(of: exitTest.id) { json in
871-
childEnvironment[Self._idEnvironmentVariableName] = String(decoding: Array(json), as: UTF8.self)
873+
childEnvironment[Self._idEnvironmentVariableName] = String(decoding: json, as: UTF8.self)
872874
}
873875

874876
typealias ResultUpdater = @Sendable (inout ExitTest.Result) -> Void
@@ -1005,7 +1007,9 @@ extension ExitTest {
10051007

10061008
for recordJSON in bytes.split(whereSeparator: \.isASCIINewline) where !recordJSON.isEmpty {
10071009
do {
1008-
try Self._processRecord(recordJSON.span.bytes, fromBackChannel: backChannel)
1010+
try recordJSON.withUnsafeBufferPointer { recordJSON in
1011+
try Self._processRecord(.init(recordJSON), fromBackChannel: backChannel)
1012+
}
10091013
} catch {
10101014
// NOTE: an error caught here indicates a decoding problem.
10111015
// TODO: should we record these issues as systemic instead?
@@ -1022,7 +1026,7 @@ extension ExitTest {
10221026
/// - backChannel: The file handle that `recordJSON` was read from.
10231027
///
10241028
/// - Throws: Any error encountered attempting to decode or process the JSON.
1025-
private static func _processRecord(_ recordJSON: borrowing RawSpan, fromBackChannel backChannel: borrowing FileHandle) throws {
1029+
private static func _processRecord(_ recordJSON: UnsafeRawBufferPointer, fromBackChannel backChannel: borrowing FileHandle) throws {
10261030
let record = try JSON.decode(ABI.Record<ABI.BackChannelVersion>.self, from: recordJSON)
10271031
guard case let .event(event) = record.kind else {
10281032
return
@@ -1089,7 +1093,9 @@ extension ExitTest {
10891093
var capturedValue = capturedValue
10901094

10911095
func open<T>(_ type: T.Type) throws -> T where T: Codable & Sendable {
1092-
return try JSON.decode(type, from: capturedValueJSON.span.bytes)
1096+
return try capturedValueJSON.withUnsafeBytes { capturedValueJSON in
1097+
try JSON.decode(type, from: capturedValueJSON)
1098+
}
10931099
}
10941100
capturedValue.wrappedValue = try open(capturedValue.typeOfWrappedValue)
10951101

@@ -1112,7 +1118,7 @@ extension ExitTest {
11121118
/// This function should only be used when the process was started via the
11131119
/// `__swiftPMEntryPoint()` function. The effect of using it under other
11141120
/// configurations is undefined.
1115-
private borrowing func _withEncodedCapturedValuesForEntryPoint(_ body: (borrowing RawSpan) throws -> Void) throws -> Void {
1121+
private borrowing func _withEncodedCapturedValuesForEntryPoint(_ body: (UnsafeRawBufferPointer) throws -> Void) throws -> Void {
11161122
for capturedValue in capturedValues {
11171123
try JSON.withEncoding(of: capturedValue.wrappedValue!) { capturedValueJSON in
11181124
try JSON.asJSONLine(capturedValueJSON, body)

Sources/Testing/Support/Additions/ArrayAdditions.swift

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -67,52 +67,6 @@ extension Array {
6767
}
6868
}
6969

70-
// MARK: - Span/RawSpan support
71-
72-
extension Array where Element == UInt8 {
73-
init(_ bytes: borrowing RawSpan) {
74-
self = bytes.withUnsafeBytes { Array($0) }
75-
}
76-
}
77-
78-
#if SWT_TARGET_OS_APPLE
79-
extension Array {
80-
/// The elements of this array as a span.
81-
///
82-
/// This property is equivalent to the `span` property in the Swift standard
83-
/// library, but is available on earlier Apple platforms.
84-
///
85-
/// For arrays with contiguous storage, getting the value of this property is
86-
/// an _O_(1) operation. For arrays with non-contiguous storage (i.e. bridged
87-
/// from Objective-C), the operation may be up to _O_(_n_).
88-
var span: Span<Element> {
89-
@_lifetime(borrow self)
90-
_read {
91-
let slice = self[...]
92-
yield slice.span
93-
}
94-
}
95-
}
96-
97-
extension String.UTF8View {
98-
/// A raw span representing this string as UTF-8, not including a trailing
99-
/// null character.
100-
///
101-
/// This property is equivalent to the `span` property in the Swift standard
102-
/// library, but is available on earlier Apple platforms.
103-
var span: Span<Element> {
104-
@_lifetime(borrow self)
105-
_read {
106-
// This implementation incurs a copy even for native Swift strings. This
107-
// isn't currently a hot path in the testing library though.
108-
yield ContiguousArray(self).span
109-
}
110-
}
111-
}
112-
#endif
113-
114-
// MARK: - Parameter pack additions
115-
11670
/// Get the number of elements in a parameter pack.
11771
///
11872
/// - Parameters:

Sources/Testing/Support/FileHandle.swift

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ extension FileHandle {
365365
// MARK: - Writing
366366

367367
extension FileHandle {
368-
/// Write a span of bytes to this file handle.
368+
/// Write a sequence of bytes to this file handle.
369369
///
370370
/// - Parameters:
371371
/// - bytes: The bytes to write. This untyped buffer is interpreted as a
@@ -376,26 +376,57 @@ extension FileHandle {
376376
///
377377
/// - Throws: Any error that occurred while writing `bytes`. If an error
378378
/// occurs while flushing the file, it is not thrown.
379-
func write(_ bytes: borrowing RawSpan, flushAfterward: Bool = true) throws {
379+
func write(_ bytes: UnsafeBufferPointer<UInt8>, flushAfterward: Bool = true) throws {
380380
try withUnsafeCFILEHandle { file in
381381
defer {
382382
if flushAfterward {
383383
_ = fflush(file)
384384
}
385385
}
386386

387-
if bytes.isEmpty {
388-
return
389-
}
390-
let countWritten = bytes.withUnsafeBytes { bytes in
391-
fwrite(bytes.baseAddress!, MemoryLayout<UInt8>.stride, bytes.count, file)
392-
}
393-
if countWritten < bytes.byteCount {
387+
let countWritten = fwrite(bytes.baseAddress!, MemoryLayout<UInt8>.stride, bytes.count, file)
388+
if countWritten < bytes.count {
394389
throw CError(rawValue: swt_errno())
395390
}
396391
}
397392
}
398393

394+
/// Write a sequence of bytes to this file handle.
395+
///
396+
/// - Parameters:
397+
/// - bytes: The bytes to write.
398+
/// - flushAfterward: Whether or not to flush the file (with `fflush()`)
399+
/// after writing. If `true`, `fflush()` is called even if an error
400+
/// occurred while writing.
401+
///
402+
/// - Throws: Any error that occurred while writing `bytes`. If an error
403+
/// occurs while flushing the file, it is not thrown.
404+
///
405+
/// - Precondition: `bytes` must provide contiguous storage.
406+
func write(_ bytes: some Sequence<UInt8>, flushAfterward: Bool = true) throws {
407+
let hasContiguousStorage: Void? = try bytes.withContiguousStorageIfAvailable { bytes in
408+
try write(bytes, flushAfterward: flushAfterward)
409+
}
410+
precondition(hasContiguousStorage != nil, "byte sequence must provide contiguous storage: \(bytes)")
411+
}
412+
413+
/// Write a sequence of bytes to this file handle.
414+
///
415+
/// - Parameters:
416+
/// - bytes: The bytes to write. This untyped buffer is interpreted as a
417+
/// sequence of `UInt8` values.
418+
/// - flushAfterward: Whether or not to flush the file (with `fflush()`)
419+
/// after writing. If `true`, `fflush()` is called even if an error
420+
/// occurred while writing.
421+
///
422+
/// - Throws: Any error that occurred while writing `bytes`. If an error
423+
/// occurs while flushing the file, it is not thrown.
424+
func write(_ bytes: UnsafeRawBufferPointer, flushAfterward: Bool = true) throws {
425+
try bytes.withMemoryRebound(to: UInt8.self) { bytes in
426+
try write(bytes, flushAfterward: flushAfterward)
427+
}
428+
}
429+
399430
/// Write a string to this file handle.
400431
///
401432
/// - Parameters:
@@ -410,7 +441,19 @@ extension FileHandle {
410441
/// `string` is converted to a UTF-8 C string (UTF-16 on Windows) and written
411442
/// to this file handle.
412443
func write(_ string: String, flushAfterward: Bool = true) throws {
413-
try write(string.utf8.span.bytes, flushAfterward: flushAfterward)
444+
try withUnsafeCFILEHandle { file in
445+
defer {
446+
if flushAfterward {
447+
_ = fflush(file)
448+
}
449+
}
450+
451+
try string.withCString { string in
452+
if EOF == fputs(string, file) {
453+
throw CError(rawValue: swt_errno())
454+
}
455+
}
456+
}
414457
}
415458
}
416459

0 commit comments

Comments
 (0)