@@ -18,13 +18,13 @@ extension AsyncBufferSequence {
1818 /// A immutable collection of bytes
1919 public struct Buffer : Sendable {
2020 #if os(Windows)
21- private var data : [ UInt8 ]
21+ internal var data : [ UInt8 ]
2222
2323 internal init ( data: [ UInt8 ] ) {
2424 self . data = data
2525 }
2626 #else
27- private var data : DispatchData
27+ internal var data : DispatchData
2828
2929 internal init ( data: DispatchData ) {
3030 self . data = data
@@ -54,7 +54,6 @@ extension AsyncBufferSequence.Buffer {
5454@available ( SubprocessSpan, * )
5555#endif
5656extension AsyncBufferSequence . Buffer {
57- #if !SubprocessSpan
5857 /// Access the raw bytes stored in this buffer
5958 /// - Parameter body: A closure with an `UnsafeRawBufferPointer` parameter that
6059 /// points to the contiguous storage for the type. If no such storage exists,
@@ -64,13 +63,6 @@ extension AsyncBufferSequence.Buffer {
6463 /// - Returns: The return value, if any, of the body closure parameter.
6564 public func withUnsafeBytes< ResultType> (
6665 _ 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
7466 ) rethrows -> ResultType {
7567 #if os(Windows)
7668 return try self . data. withUnsafeBytes ( body)
@@ -88,44 +80,48 @@ extension AsyncBufferSequence.Buffer {
8880 #if SubprocessSpan
8981 // Access the storge backing this Buffer
9082 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+ }
112107 }
113108 }
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+ // return array.bytes
121+ let ptr = array. withUnsafeBytes { $0 }
122+ let span = RawSpan ( _unsafeBytes: ptr)
123+ return _overrideLifetime ( of: span, to: self )
124+ }
129125 }
130126 }
131127 #endif // SubprocessSpan
@@ -159,3 +155,41 @@ extension AsyncBufferSequence.Buffer: Equatable, Hashable {
159155 }
160156 #endif
161157}
158+
159+ // MARK: - Initializers
160+ #if SubprocessSpan
161+ @available ( SubprocessSpan, * )
162+ #endif
163+ extension String {
164+ /// Create a String with the given encoding from `Buffer`.
165+ /// - Parameters:
166+ /// - buffer: the buffer to copy from
167+ /// - encoding: the encoding to encode Self with
168+ public init ? < Encoding: _UnicodeEncoding > ( buffer: AsyncBufferSequence . Buffer , as encoding: Encoding . Type ) {
169+ #if os(Windows)
170+ return String ( validating: self . data, as: encoding)
171+ #else
172+ self = buffer. withUnsafeBytes { ptr in
173+ return String (
174+ decoding: ptr. bindMemory ( to: Encoding . CodeUnit. self) . lazy. map { $0 } ,
175+ as: encoding
176+ )
177+ }
178+ #endif
179+ }
180+ }
181+
182+ #if SubprocessSpan
183+ @available ( SubprocessSpan, * )
184+ #endif
185+ extension Array where Element == UInt8 {
186+ /// Create an Array from `Buffer`
187+ /// - Parameter buffer: the buffer to copy from
188+ public init ( buffer: AsyncBufferSequence . Buffer ) {
189+ #if os(Windows)
190+ self = buffer. data
191+ #else
192+ self = Array ( buffer. data)
193+ #endif
194+ }
195+ }
0 commit comments