Skip to content

Commit 1f93566

Browse files
authored
Merge pull request #80517 from glessard/rdar138440979-MutableSpan-mutableBytes
[SE-0467] add mutableBytes to MutableSpan
2 parents 4b5d519 + cb39014 commit 1f93566

File tree

4 files changed

+72
-7
lines changed

4 files changed

+72
-7
lines changed

stdlib/public/core/Span/MutableRawSpan.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,17 @@ extension MutableRawSpan {
109109
}
110110

111111
@_alwaysEmitIntoClient
112-
@lifetime(copy elements)
112+
@lifetime(&elements)
113113
public init<Element: BitwiseCopyable>(
114-
_elements elements: consuming MutableSpan<Element>
114+
_elements elements: inout MutableSpan<Element>
115115
) {
116-
let bytes = unsafe UnsafeMutableRawBufferPointer(
117-
start: elements._pointer,
118-
count: elements.count &* MemoryLayout<Element>.stride
116+
let (start, count) = unsafe (elements._pointer, elements._count)
117+
let span = unsafe MutableRawSpan(
118+
_unchecked: start,
119+
byteCount: count == 1 ? MemoryLayout<Element>.size
120+
: count &* MemoryLayout<Element>.stride
119121
)
120-
let span = unsafe MutableRawSpan(_unsafeBytes: bytes)
121-
self = unsafe _overrideLifetime(span, copying: elements)
122+
self = unsafe _overrideLifetime(span, mutating: &elements)
122123
}
123124
}
124125

stdlib/public/core/Span/MutableSpan.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,17 @@ extension MutableSpan where Element: BitwiseCopyable {
256256
RawSpan(_mutableSpan: self)
257257
}
258258
}
259+
260+
/// Construct a MutableRawSpan over the memory represented by this span
261+
///
262+
/// - Returns: a MutableRawSpan over the memory represented by this span
263+
@_alwaysEmitIntoClient
264+
public var mutableBytes: MutableRawSpan {
265+
@lifetime(&self)
266+
mutating get {
267+
MutableRawSpan(_elements: &self)
268+
}
269+
}
259270
}
260271

261272
@available(SwiftCompatibilitySpan 5.0, *)

test/stdlib/Span/MutableRawSpanTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,38 @@ suite.test("Basic Initializer")
3636
}
3737
}
3838

39+
private struct Padded: BitwiseCopyable {
40+
var storage: (Int64, Int8)
41+
}
42+
43+
suite.test("Initializer from MutableSpan")
44+
.require(.stdlib_6_2).code {
45+
guard #available(SwiftStdlib 6.2, *) else { return }
46+
47+
var array = [0, 1, 2].map({ Padded(storage: (Int64($0), Int8($0))) })
48+
array.withUnsafeMutableBufferPointer {
49+
var span = MutableSpan(_unsafeElements: $0)
50+
var rawSpan = MutableRawSpan(_elements: &span)
51+
52+
expectEqual(rawSpan.byteCount, $0.count * MemoryLayout<Padded>.stride)
53+
54+
rawSpan.storeBytes(of: 15, as: Int64.self)
55+
}
56+
expectEqual(array[0].storage.0, 15)
57+
58+
var slice = array.prefix(1)
59+
slice.withUnsafeMutableBufferPointer {
60+
expectEqual($0.count, 1)
61+
var span = MutableSpan(_unsafeElements: $0)
62+
var rawSpan = MutableRawSpan(_elements: &span)
63+
64+
expectEqual(rawSpan.byteCount, MemoryLayout<Padded>.size)
65+
66+
rawSpan.storeBytes(of: 3, as: Int64.self)
67+
}
68+
expectEqual(slice[0].storage.0, 3)
69+
}
70+
3971
suite.test("isEmpty property")
4072
.skip(.custom(
4173
{ if #available(SwiftStdlib 6.2, *) { false } else { true } },

test/stdlib/Span/MutableSpanTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,28 @@ suite.test("RawSpan from MutableSpan")
122122
let span = MutableSpan(_unsafeStart: p, count: c)
123123
let bytes = span.bytes
124124
expectEqual(bytes.byteCount, count*MemoryLayout<Int>.stride)
125+
let v = bytes.unsafeLoad(
126+
fromByteOffset: MemoryLayout<Int>.stride, as: Int.self
127+
)
128+
expectEqual(v, 1)
129+
}
130+
}
131+
132+
suite.test("MutableRawSpan from MutableSpan")
133+
.require(.stdlib_6_2).code {
134+
guard #available(SwiftStdlib 6.2, *) else { return }
135+
136+
let count = 4
137+
var array = Array(0..<count)
138+
expectEqual(array[0], 0)
139+
array.withUnsafeMutableBufferPointer {
140+
let (p, c) = ($0.baseAddress!, $0.count)
141+
var span = MutableSpan(_unsafeStart: p, count: c)
142+
var bytes = span.mutableBytes
143+
expectEqual(bytes.byteCount, count*MemoryLayout<Int>.stride)
144+
bytes.storeBytes(of: 1, as: Int.self)
125145
}
146+
expectEqual(array[0], 1)
126147
}
127148

128149
suite.test("indices property")

0 commit comments

Comments
 (0)