Skip to content

Commit 5bae1f5

Browse files
support noncopyable; use _read and _modify for subscript
1 parent ed9e0cc commit 5bae1f5

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

Sources/VariableLengthArray/VLArray.swift

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/// Variable-length array, most likely stored on the stack.
44
///
55
/// - Warning: May fall back to heap allocation if the compiler/runtime decides the allocation is too big for the stack.
6-
public struct VLArray<Element>: ~Copyable, @unchecked Sendable {
6+
public struct VLArray<Element>: ~Copyable, @unchecked Sendable where Element: ~Copyable {
77
public typealias Index = Int
88

99
@usableFromInline
@@ -96,6 +96,23 @@ public struct VLArray<Element>: ~Copyable, @unchecked Sendable {
9696
_storage.index(before: i)
9797
}
9898

99+
/// Exchanges the values at the specified indices of the buffer.
100+
///
101+
/// Both parameters must be valid indices of the buffer, and not
102+
/// equal to `endIndex`. Passing the same index as both `i` and `j` has no
103+
/// effect.
104+
///
105+
/// - Parameters:
106+
/// - i: The index of the first value to swap.
107+
/// - j: The index of the second value to swap.
108+
@inlinable
109+
public mutating func swapAt(_ i: Index, _ j: Index) {
110+
_storage.swapAt(i, j)
111+
}
112+
}
113+
114+
// MARK: Subscript
115+
extension VLArray {
99116
/// Accesses the element at the specified position.
100117
///
101118
/// The following example uses the buffer pointer's subscript to access and
@@ -126,19 +143,37 @@ public struct VLArray<Element>: ~Copyable, @unchecked Sendable {
126143
get { _storage[i] }
127144
set { _storage[i] = newValue }
128145
}
129-
130-
/// Exchanges the values at the specified indices of the buffer.
146+
}
147+
extension VLArray where Element: ~Copyable {
148+
/// Accesses the element at the specified position.
131149
///
132-
/// Both parameters must be valid indices of the buffer, and not
133-
/// equal to `endIndex`. Passing the same index as both `i` and `j` has no
134-
/// effect.
150+
/// The following example uses the buffer pointer's subscript to access and
151+
/// modify the elements of a mutable buffer pointing to the contiguous
152+
/// contents of an array:
135153
///
136-
/// - Parameters:
137-
/// - i: The index of the first value to swap.
138-
/// - j: The index of the second value to swap.
154+
/// var numbers = [1, 2, 3, 4, 5]
155+
/// numbers.withUnsafeMutableBufferPointer { buffer in
156+
/// for i in stride(from: buffer.startIndex, to: buffer.endIndex - 1, by: 2) {
157+
/// let x = buffer[i]
158+
/// buffer[i + 1] = buffer[i]
159+
/// buffer[i] = x
160+
/// }
161+
/// }
162+
/// print(numbers)
163+
/// // Prints "[2, 1, 4, 3, 5]"
164+
///
165+
/// Uninitialized memory cannot be initialized to a nontrivial type
166+
/// using this subscript. Instead, use an initializing method, such as
167+
/// `initializeElement(at:to:)`
168+
///
169+
/// - Note: Bounds checks for `i` are performed only in debug mode.
170+
///
171+
/// - Parameter i: The position of the element to access. `i` must be in the
172+
/// range `0..<count`.
139173
@inlinable
140-
public mutating func swapAt(_ i: Index, _ j: Index) {
141-
_storage.swapAt(i, j)
174+
public subscript(i: Index) -> Element {
175+
_read { yield _storage[i] }
176+
_modify { yield &_storage[i] }
142177
}
143178
}
144179

0 commit comments

Comments
 (0)