Looking for feedback before submitting a PR: https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/xxxx-corelibs-unsafebytes.md
···
—
Change (Dispatch)Data.withUnsafeBytes to use UnsafeMutableBufferPointer
Proposal: SE-NNNN <https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/NNNN-filename.md>
Authors: Karl Wagner <https://github.com/karwa>
Review Manager: TBD
Status: Awaiting review
During the review process, add the following fields as needed:
Decision Notes: Rationale <https://lists.swift.org/pipermail/swift-evolution/>, Additional Commentary <https://lists.swift.org/pipermail/swift-evolution/>
Bugs: SR-NNNN <Issues · apple/swift-issues · GitHub, SR-MMMM <Issues · apple/swift-issues · GitHub;
Previous Revision: 1 <https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md>
Previous Proposal: SE-XXXX <https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/XXXX-filename.md>
<https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/xxxx-corelibs-unsafebytes.md#introduction>Introduction
The standard library's Array and ContiguousArray types expose the method withUnsafeBytes, which allows you to view their contents as a contiguous collection of bytes. The core libraries Foundation and Dispatch contain types which wrap some allocated data, but their withUnsafeBytes method only allows you to view the contents as a pointer to a contiguous memory location of a given type.
Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
<https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/xxxx-corelibs-unsafebytes.md#motivation>Motivation
The current situation makes it awkward to write generic code. Personally, I use the following extension in my projects to sort the naming confusion out:
protocol ContiguousByteCollection {
func withUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T
}
// stdlib types are fine.
extension Array: ContiguousByteCollection {}
extension ArraySlice: ContiguousByteCollection {}
extension ContiguousArray: ContiguousByteCollection {}
// corelibs types give us a pointer<T>, should be: { pointer<char>, count }
#if canImport(Dispatch)
import Dispatch
extension DispatchData : ContiguousByteCollection {
func withUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
return try withUnsafeBytes { try body(UnsafeRawBufferPointer(start: $0, count: count)) }
}
}
#endif
#if canImport(Foundation)
import Foundation
extension Data : ContiguousByteCollection {
func withUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
return try withUnsafeBytes { try body(UnsafeRawBufferPointer(start: $0, count: count)) }
}
}
#endif
Conceptually, the corelibs types are untyped regions of memory, and it would make sense for them to adopt the UnsafeRawBufferPointer model.
The proposed solution would be to deprecate the current methods on (Dispatch)Data (with 2 generic parameters), and replace them with methods with identical signatures to Array (with 1 generic parameter).
To be deprecated:
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
Replaced with:
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
<https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/xxxx-corelibs-unsafebytes.md#source-compatibility>Source compatibility
Source-breaking. Users binding a (Dispatch)Data to an UnsafePointer would instead have to call:
buffer.baseAddress!.assumingMemoryBound(to: T.self)
Which is a bit more to type, although maybe the deprecation of the old function could provide this replacement as a fix-it.
<https://github.com/karwa/swift-evolution/blob/corelibs-unsafebytes/proposals/xxxx-corelibs-unsafebytes.md#effect-on-api-resilience>Effect on API resilience
Source-breaking change to corelibs APIs.
A different method on Data and DispatchData, providing an UnsafeRawBufferPointer? There would still be a naming discrepency between the stdlib and corelibs types