@@ -33,98 +33,73 @@ public struct HTTPClientResponse: Sendable {
3333 /// The body of this HTTP response.
3434 public var body : Body
3535
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-
5136 init (
5237 bag: Transaction ,
5338 version: HTTPVersion ,
5439 status: HTTPResponseStatus ,
5540 headers: HTTPHeaders
5641 ) {
57- self . body = Body ( bag)
5842 self . version = version
5943 self . status = status
6044 self . headers = headers
45+ self . body = Body ( TransactionBody ( bag) )
6146 }
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 ( )
8253 }
8354}
8455
8556@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+ public struct AsyncIterator : AsyncIteratorProtocol {
66+ @usableFromInline var storage : Either < TransactionBody . AsyncIterator , AnyAsyncSequence < ByteBuffer > . AsyncIterator >
67+
68+ @inlinable init ( storage: Either < TransactionBody . AsyncIterator , AnyAsyncSequence < ByteBuffer > . AsyncIterator > ) {
69+ self . storage = storage
70+ }
71+
72+ @inlinable public mutating func next( ) async throws -> ByteBuffer ? {
73+ try await storage. next ( )
74+ }
9575 }
76+
77+ @usableFromInline var storage : Either < TransactionBody , AnyAsyncSequence < ByteBuffer > >
9678
97- deinit {
98- self . transaction . responseBodyDeinited ( )
79+ @ inlinable public func makeAsyncIterator ( ) -> AsyncIterator {
80+ . init ( storage : storage . makeAsyncIterator ( ) )
9981 }
10082 }
10183}
10284
10385@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
10486extension 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- }
87+ @inlinable init ( _ body: TransactionBody ) {
88+ self . storage = . a( body)
89+ }
90+
91+ @inlinable public init < SequenceOfBytes> (
92+ _ sequenceOfBytes: SequenceOfBytes
93+ ) where SequenceOfBytes: AsyncSequence & Sendable , SequenceOfBytes. Element == ByteBuffer {
94+ self . storage = . b( AnyAsyncSequence ( sequenceOfBytes) )
95+ }
96+
97+ public init ( ) {
98+ self . init ( EmptyCollection ( ) . asAsyncSequence ( ) )
99+ }
100+
101+ public init ( _ byteBuffer: ByteBuffer ) {
102+ self . init ( CollectionOfOne ( byteBuffer) . asAsyncSequence ( ) )
128103 }
129104}
130105
0 commit comments