13
13
// COW helpers
14
14
extension _StringGuts {
15
15
internal var nativeCapacity : Int ? {
16
- guard hasNativeStorage else { return nil }
17
- return _object. nativeStorage . capacity
16
+ guard hasNativeStorage else { return nil }
17
+ return _object. withNativeStorage { $0 . capacity }
18
18
}
19
19
20
20
internal var nativeUnusedCapacity : Int ? {
21
- guard hasNativeStorage else { return nil }
22
- return _object. nativeStorage . unusedCapacity
21
+ guard hasNativeStorage else { return nil }
22
+ return _object. withNativeStorage { $0 . unusedCapacity }
23
23
}
24
24
25
25
// If natively stored and uniquely referenced, return the storage's total
26
26
// capacity. Otherwise, nil.
27
27
internal var uniqueNativeCapacity : Int ? {
28
28
@inline ( __always) mutating get {
29
29
guard isUniqueNative else { return nil }
30
- return _object. nativeStorage . capacity
30
+ return _object. withNativeStorage { $0 . capacity }
31
31
}
32
32
}
33
33
@@ -36,7 +36,7 @@ extension _StringGuts {
36
36
internal var uniqueNativeUnusedCapacity : Int ? {
37
37
@inline ( __always) mutating get {
38
38
guard isUniqueNative else { return nil }
39
- return _object. nativeStorage . unusedCapacity
39
+ return _object. withNativeStorage { $0 . unusedCapacity }
40
40
}
41
41
}
42
42
@@ -54,6 +54,20 @@ extension _StringGuts {
54
54
55
55
// Range-replaceable operation support
56
56
extension _StringGuts {
57
+ @inline ( __always)
58
+ internal mutating func updateNativeStorage< R> (
59
+ _ body: ( __StringStorage ) -> R
60
+ ) -> R {
61
+ let storage = self . _object. nativeStorage
62
+ self = _StringGuts ( )
63
+ defer {
64
+ // We re-initialize from the modified storage to pick up new count, flags,
65
+ // etc.
66
+ self = _StringGuts ( storage)
67
+ }
68
+ return body ( storage)
69
+ }
70
+
57
71
@inlinable
58
72
internal init ( _initialCapacity capacity: Int ) {
59
73
self . init ( )
@@ -243,11 +257,7 @@ extension _StringGuts {
243
257
internal mutating func appendInPlace(
244
258
_ other: UnsafeBufferPointer < UInt8 > , isASCII: Bool
245
259
) {
246
- self . _object. nativeStorage. appendInPlace ( other, isASCII: isASCII)
247
-
248
- // We re-initialize from the modified storage to pick up new count, flags,
249
- // etc.
250
- self = _StringGuts ( self . _object. nativeStorage)
260
+ updateNativeStorage { $0. appendInPlace ( other, isASCII: isASCII) }
251
261
}
252
262
253
263
@inline ( never) // slow-path
@@ -256,11 +266,7 @@ extension _StringGuts {
256
266
_internalInvariant ( self . uniqueNativeUnusedCapacity != nil )
257
267
258
268
var iter = Substring ( other) . utf8. makeIterator ( )
259
- self . _object. nativeStorage. appendInPlace ( & iter, isASCII: other. isASCII)
260
-
261
- // We re-initialize from the modified storage to pick up new count, flags,
262
- // etc.
263
- self = _StringGuts ( self . _object. nativeStorage)
269
+ updateNativeStorage { $0. appendInPlace ( & iter, isASCII: other. isASCII) }
264
270
}
265
271
266
272
internal mutating func clear( ) {
@@ -270,8 +276,7 @@ extension _StringGuts {
270
276
}
271
277
272
278
// Reset the count
273
- _object. nativeStorage. clear ( )
274
- self = _StringGuts ( _object. nativeStorage)
279
+ updateNativeStorage { $0. clear ( ) }
275
280
}
276
281
277
282
internal mutating func remove( from lower: Index , to upper: Index ) {
@@ -281,10 +286,7 @@ extension _StringGuts {
281
286
_internalInvariant ( lowerOffset <= upperOffset && upperOffset <= self . count)
282
287
283
288
if isUniqueNative {
284
- _object. nativeStorage. remove ( from: lowerOffset, to: upperOffset)
285
- // We re-initialize from the modified storage to pick up new count, flags,
286
- // etc.
287
- self = _StringGuts ( self . _object. nativeStorage)
289
+ updateNativeStorage { $0. remove ( from: lowerOffset, to: upperOffset) }
288
290
return
289
291
}
290
292
@@ -412,8 +414,9 @@ extension _StringGuts {
412
414
413
415
let start = bounds. lowerBound. _encodedOffset
414
416
let end = bounds. upperBound. _encodedOffset
415
- _object. nativeStorage. replace ( from: start, to: end, with: codeUnits)
416
- self = _StringGuts ( _object. nativeStorage)
417
+ updateNativeStorage {
418
+ $0. replace ( from: start, to: end, with: codeUnits)
419
+ }
417
420
return Range ( _uncheckedBounds: ( start, start + codeUnits. count) )
418
421
}
419
422
@@ -435,9 +438,10 @@ extension _StringGuts {
435
438
436
439
let start = bounds. lowerBound. _encodedOffset
437
440
let end = bounds. upperBound. _encodedOffset
438
- _object. nativeStorage. replace (
439
- from: start, to: end, with: codeUnits, replacementCount: replCount)
440
- self = _StringGuts ( _object. nativeStorage)
441
+ updateNativeStorage {
442
+ $0. replace (
443
+ from: start, to: end, with: codeUnits, replacementCount: replCount)
444
+ }
441
445
return Range ( _uncheckedBounds: ( start, start + replCount) )
442
446
}
443
447
0 commit comments