Hello all, this is a new proposal to add initializers to form a single-element Span over any value, and to form a single-element MutableSpan over any mutable value. The evolution pull request is at [pitch] `Span` over a single value by glessard · Pull Request #3445 · swiftlang/swift-evolution · GitHub, and most of the content follows.
Motivation
Occasionally, programmers need adaptors between single values and Span-taking API. Currently it is possible to use the span property of CollectionOfOne in order to pass a single value to a Span parameter, but it requires a copy that Span doesn't need, or that non-copyable values cannot support. We can provide initializers for Span, RawSpan, MutableSpan and MutableRawSpan that borrow single values in place.
These initializers will also act as safe versions of withUnsafePointer(to:), withUnsafeMutablePointer(to:), withUnsafeBytes(of:) and withUnsafeMutableBytes(of:)
Proposed solution
Span and MutableSpan gain unlabeled initializers that form a span of count 1
over a single value:
let header = PacketHeader(...)
let c = checksum(Span(header).bytes) // borrows `header` in place
var timestamp = UInt64.zero
var span = MutableSpan(×tamp)
parser.read(into: span.mutableBytes) // writes directly into `timestamp`
Similarly, RawSpan and MutableRawSpan gain initializers that form spans over the bytes of a single value:
let header = PacketHeader(...)
let c = checksum(RawSpan(header))
var timestamp = UInt64.zero
var bytes = MutableRawSpan(×tamp)
parser.read(into: &bytes)
Detailed design
Span
extension Span where Element: ~Copyable {
/// Create a span over the single value passed as a parameter.
///
/// - Parameters:
/// - value: a value to be borrowed by the span
@_lifetime(borrow value)
public init(_ value: borrowing Element)
}
MutableSpan
extension MutableSpan where Element: ~Copyable {
/// Create a mutable span over the single value passed as a parameter.
///
/// The `MutableSpan` created by this initializer will represent a
/// mutation of `value`.
///
/// - Parameters:
/// - value: a value to be mutated through the span
@_lifetime(&value)
public init(_ value: inout Element)
}
RawSpan
extension RawSpan {
/// Create a span over the bytes of the single value passed as a parameter.
///
/// The `RawSpan` created by this initializer will have a byteCount of
/// `MemoryLayout<Element>.size` bytes.
///
/// - Parameters:
/// - value: a value to be borrowed by the span
@_lifetime(borrow value)
public init<Element: ConvertibleToBytes>(_ value: borrowing Element)
}
MutableRawSpan
extension MutableRawSpan {
/// Create a mutable span over the bytes of the value passed as a parameter.
///
/// The `MutableRawSpan` created by this initializer will represent a
/// mutation of `value`. It will have a byteCount of
/// `MemoryLayout<Element>.size` bytes.
///
/// - Parameters:
/// - value: a value to be mutated through the span
@_lifetime(&value)
public init<Element: ConvertibleToBytes & ConvertibleFromBytes>(
_ value: inout Element
)
}