@@ -18,13 +18,13 @@ extension AsyncBufferSequence {
18
18
/// A immutable collection of bytes
19
19
public struct Buffer : Sendable {
20
20
#if os(Windows)
21
- private var data : [ UInt8 ]
21
+ internal var data : [ UInt8 ]
22
22
23
23
internal init ( data: [ UInt8 ] ) {
24
24
self . data = data
25
25
}
26
26
#else
27
- private var data : DispatchData
27
+ internal var data : DispatchData
28
28
29
29
internal init ( data: DispatchData ) {
30
30
self . data = data
@@ -54,7 +54,6 @@ extension AsyncBufferSequence.Buffer {
54
54
@available ( SubprocessSpan, * )
55
55
#endif
56
56
extension AsyncBufferSequence . Buffer {
57
- #if !SubprocessSpan
58
57
/// Access the raw bytes stored in this buffer
59
58
/// - Parameter body: A closure with an `UnsafeRawBufferPointer` parameter that
60
59
/// points to the contiguous storage for the type. If no such storage exists,
@@ -64,13 +63,6 @@ extension AsyncBufferSequence.Buffer {
64
63
/// - Returns: The return value, if any, of the body closure parameter.
65
64
public func withUnsafeBytes< ResultType> (
66
65
_ body: ( UnsafeRawBufferPointer ) throws -> ResultType
67
- ) rethrows -> ResultType {
68
- return try self . _withUnsafeBytes ( body)
69
- }
70
- #endif // !SubprocessSpan
71
-
72
- internal func _withUnsafeBytes< ResultType> (
73
- _ body: ( UnsafeRawBufferPointer ) throws -> ResultType
74
66
) rethrows -> ResultType {
75
67
#if os(Windows)
76
68
return try self . data. withUnsafeBytes ( body)
@@ -88,44 +80,46 @@ extension AsyncBufferSequence.Buffer {
88
80
#if SubprocessSpan
89
81
// Access the storge backing this Buffer
90
82
public var bytes : RawSpan {
91
- var backing : SpanBacking ?
92
- #if os(Windows)
93
- self . data. withUnsafeBufferPointer {
94
- backing = . pointer( $0)
95
- }
96
- #else
97
- self . data. enumerateBytes { buffer, byteIndex, stop in
98
- if _fastPath ( backing == nil ) {
99
- // In practice, almost all `DispatchData` is contiguous
100
- backing = . pointer( buffer)
101
- } else {
102
- // This DispatchData is not contiguous. We need to copy
103
- // the bytes out
104
- let contents = Array ( buffer)
105
- switch backing! {
106
- case . pointer( let ptr) :
107
- // Convert the ptr to array
108
- let existing = Array ( ptr)
109
- backing = . array( existing + contents)
110
- case . array( let array) :
111
- backing = . array( array + contents)
83
+ @lifetime ( borrow self)
84
+ borrowing get {
85
+ var backing : SpanBacking ?
86
+ #if os(Windows)
87
+ self . data. withUnsafeBufferPointer {
88
+ backing = . pointer( $0)
89
+ }
90
+ #else
91
+ self . data. enumerateBytes { buffer, byteIndex, stop in
92
+ if _fastPath ( backing == nil ) {
93
+ // In practice, almost all `DispatchData` is contiguous
94
+ backing = . pointer( buffer)
95
+ } else {
96
+ // This DispatchData is not contiguous. We need to copy
97
+ // the bytes out
98
+ let contents = Array ( buffer)
99
+ switch backing! {
100
+ case . pointer( let ptr) :
101
+ // Convert the ptr to array
102
+ let existing = Array ( ptr)
103
+ backing = . array( existing + contents)
104
+ case . array( let array) :
105
+ backing = . array( array + contents)
106
+ }
112
107
}
113
108
}
114
- }
115
- #endif
116
- guard let backing = backing else {
117
- let empty = UnsafeRawBufferPointer ( start: nil , count: 0 )
118
- let span = RawSpan ( _unsafeBytes: empty)
119
- return _overrideLifetime ( of: span, to: self )
120
- }
121
- switch backing {
122
- case . pointer( let ptr) :
123
- let span = RawSpan ( _unsafeElements: ptr)
124
- return _overrideLifetime ( of: span, to: self )
125
- case . array( let array) :
126
- let ptr = array. withUnsafeBytes { $0 }
127
- let span = RawSpan ( _unsafeBytes: ptr)
128
- return _overrideLifetime ( of: span, to: self )
109
+ #endif
110
+ guard let backing = backing else {
111
+ let empty = UnsafeRawBufferPointer ( start: nil , count: 0 )
112
+ let span = RawSpan ( _unsafeBytes: empty)
113
+ return _overrideLifetime ( of: span, to: self )
114
+ }
115
+ switch backing {
116
+ case . pointer( let ptr) :
117
+ let span = RawSpan ( _unsafeElements: ptr)
118
+ return _overrideLifetime ( of: span, to: self )
119
+ case . array( let array) :
120
+ let span = array. bytes
121
+ return _overrideLifetime ( of: span, to: self )
122
+ }
129
123
}
130
124
}
131
125
#endif // SubprocessSpan
@@ -159,3 +153,42 @@ extension AsyncBufferSequence.Buffer: Equatable, Hashable {
159
153
}
160
154
#endif
161
155
}
156
+
157
+ // MARK: - Initializers
158
+ #if SubprocessSpan
159
+ @available ( SubprocessSpan, * )
160
+ #endif
161
+ extension String {
162
+ /// Create a String with the given encoding from `Buffer`.
163
+ /// - Parameters:
164
+ /// - buffer: the buffer to copy from
165
+ /// - encoding: the encoding to encode Self with
166
+ public init ? < Encoding: _UnicodeEncoding > ( buffer: AsyncBufferSequence . Buffer , as encoding: Encoding . Type ) {
167
+ #if os(Windows)
168
+ let source = buffer. data. map { Encoding . CodeUnit ( $0) }
169
+ self = String ( decoding: source, as: encoding)
170
+ #else
171
+ self = buffer. withUnsafeBytes { ptr in
172
+ return String (
173
+ decoding: ptr. bindMemory ( to: Encoding . CodeUnit. self) . lazy. map { $0 } ,
174
+ as: encoding
175
+ )
176
+ }
177
+ #endif
178
+ }
179
+ }
180
+
181
+ #if SubprocessSpan
182
+ @available ( SubprocessSpan, * )
183
+ #endif
184
+ extension Array where Element == UInt8 {
185
+ /// Create an Array from `Buffer`
186
+ /// - Parameter buffer: the buffer to copy from
187
+ public init ( buffer: AsyncBufferSequence . Buffer ) {
188
+ #if os(Windows)
189
+ self = buffer. data
190
+ #else
191
+ self = Array ( buffer. data)
192
+ #endif
193
+ }
194
+ }
0 commit comments