@@ -33,98 +33,74 @@ public struct HTTPClientResponse: Sendable {
33
33
/// The body of this HTTP response.
34
34
public var body : Body
35
35
36
- /// A representation of the response body for an HTTP response.
37
- ///
38
- /// The body is streamed as an `AsyncSequence` of `ByteBuffer`, where each `ByteBuffer` contains
39
- /// an arbitrarily large chunk of data. The boundaries between `ByteBuffer` objects in the sequence
40
- /// are entirely synthetic and have no semantic meaning.
41
- public struct Body : Sendable {
42
- private let bag : Transaction
43
- private let reference : ResponseRef
44
-
45
- fileprivate init ( _ transaction: Transaction ) {
46
- self . bag = transaction
47
- self . reference = ResponseRef ( transaction: transaction)
48
- }
49
- }
50
-
51
36
init (
52
37
bag: Transaction ,
53
38
version: HTTPVersion ,
54
39
status: HTTPResponseStatus ,
55
40
headers: HTTPHeaders
56
41
) {
57
- self . body = Body ( bag)
58
42
self . version = version
59
43
self . status = status
60
44
self . headers = headers
45
+ self . body = Body ( TransactionBody ( bag) )
61
46
}
62
- }
63
-
64
- @available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
65
- extension HTTPClientResponse . Body : AsyncSequence {
66
- public typealias Element = AsyncIterator . Element
67
-
68
- public struct AsyncIterator : AsyncIteratorProtocol {
69
- private let stream : IteratorStream
70
-
71
- fileprivate init ( stream: IteratorStream ) {
72
- self . stream = stream
73
- }
74
-
75
- public mutating func next( ) async throws -> ByteBuffer ? {
76
- try await self . stream. next ( )
77
- }
78
- }
79
-
80
- public func makeAsyncIterator( ) -> AsyncIterator {
81
- AsyncIterator ( stream: IteratorStream ( bag: self . bag) )
47
+
48
+ @inlinable public init ( ) {
49
+ self . version = . http1_1
50
+ self . status = . ok
51
+ self . headers = [ : ]
52
+ self . body = Body ( )
82
53
}
83
54
}
84
55
85
56
@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
86
- extension HTTPClientResponse . Body {
87
- /// The purpose of this object is to inform the transaction about the response body being deinitialized.
88
- /// If the users has not called `makeAsyncIterator` on the body, before it is deinited, the http
89
- /// request needs to be cancelled.
90
- fileprivate final class ResponseRef : Sendable {
91
- private let transaction : Transaction
92
-
93
- init ( transaction: Transaction ) {
94
- self . transaction = transaction
57
+ extension HTTPClientResponse {
58
+ /// A representation of the response body for an HTTP response.
59
+ ///
60
+ /// The body is streamed as an `AsyncSequence` of `ByteBuffer`, where each `ByteBuffer` contains
61
+ /// an arbitrarily large chunk of data. The boundaries between `ByteBuffer` objects in the sequence
62
+ /// are entirely synthetic and have no semantic meaning.
63
+ public struct Body : AsyncSequence , Sendable {
64
+ public typealias Element = ByteBuffer
65
+ @usableFromInline typealias Storage = Either < TransactionBody , AnyAsyncSequence < ByteBuffer > >
66
+ public struct AsyncIterator : AsyncIteratorProtocol {
67
+ @usableFromInline var storage : Storage . AsyncIterator
68
+
69
+ @inlinable init ( storage: Storage . AsyncIterator ) {
70
+ self . storage = storage
71
+ }
72
+
73
+ @inlinable public mutating func next( ) async throws -> ByteBuffer ? {
74
+ try await storage. next ( )
75
+ }
95
76
}
77
+
78
+ @usableFromInline var storage : Storage
96
79
97
- deinit {
98
- self . transaction . responseBodyDeinited ( )
80
+ @ inlinable public func makeAsyncIterator ( ) -> AsyncIterator {
81
+ . init ( storage : storage . makeAsyncIterator ( ) )
99
82
}
100
83
}
101
84
}
102
85
103
86
@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
104
87
extension HTTPClientResponse . Body {
105
- internal class IteratorStream {
106
- struct ID : Hashable {
107
- private let objectID : ObjectIdentifier
108
-
109
- init ( _ object: IteratorStream ) {
110
- self . objectID = ObjectIdentifier ( object)
111
- }
112
- }
113
-
114
- private var id : ID { ID ( self ) }
115
- private let bag : Transaction
116
-
117
- init ( bag: Transaction ) {
118
- self . bag = bag
119
- }
120
-
121
- deinit {
122
- self . bag. responseBodyIteratorDeinited ( streamID: self . id)
123
- }
124
-
125
- func next( ) async throws -> ByteBuffer ? {
126
- try await self . bag. nextResponsePart ( streamID: self . id)
127
- }
88
+ @inlinable init ( _ body: TransactionBody ) {
89
+ self . storage = . a( body)
90
+ }
91
+
92
+ @inlinable public init < SequenceOfBytes> (
93
+ _ sequenceOfBytes: SequenceOfBytes
94
+ ) where SequenceOfBytes: AsyncSequence & Sendable , SequenceOfBytes. Element == ByteBuffer {
95
+ self . storage = . b( AnyAsyncSequence ( sequenceOfBytes) )
96
+ }
97
+
98
+ public init ( ) {
99
+ self . init ( EmptyCollection ( ) . asAsyncSequence ( ) )
100
+ }
101
+
102
+ public init ( _ byteBuffer: ByteBuffer ) {
103
+ self . init ( CollectionOfOne ( byteBuffer) . asAsyncSequence ( ) )
128
104
}
129
105
}
130
106
0 commit comments