@@ -169,6 +169,7 @@ extension _StringGuts {
169
169
get { return _twoByteCodeUnitBit }
170
170
}
171
171
172
+ @_inlineable
172
173
public // @testable
173
174
var isSingleByte : Bool {
174
175
@inline ( __always) get {
@@ -178,11 +179,13 @@ extension _StringGuts {
178
179
}
179
180
}
180
181
182
+ @_inlineable
181
183
public // @testable
182
184
var byteWidth : Int {
183
185
@inline ( __always) get { return isSingleByte ? 1 : 2 }
184
186
}
185
187
188
+ @_inlineable
186
189
@_versioned
187
190
var bitWidth : Int {
188
191
@inline ( __always) get { return byteWidth &<< 3 }
@@ -264,7 +267,7 @@ extension _StringGuts {
264
267
@_versioned
265
268
internal
266
269
var _isEmptyLiteral : Bool {
267
- return _isUnmanaged && _unmanagedRawStart == _emptyStringBase
270
+ return _isUnmanaged && _unmanagedCount == 0
268
271
}
269
272
}
270
273
@@ -976,6 +979,7 @@ extension _StringGuts {
976
979
@_inlineable
977
980
public // @testable
978
981
func _extractSlice( _ range: Range < Int > ) -> _StringGuts {
982
+ if range. isEmpty { return _StringGuts ( ) }
979
983
if range == 0 ..< count { return self }
980
984
switch ( isASCII, _isUnmanaged) {
981
985
case ( true , true ) :
@@ -1265,23 +1269,26 @@ extension _StringGuts {
1265
1269
}
1266
1270
1267
1271
extension _StringGuts {
1268
- public mutating func replaceSubrange< C> (
1272
+ @_versioned
1273
+ mutating func _replaceSubrange< C, CodeUnit> (
1269
1274
_ bounds: Range < Int > ,
1270
- with newElements: C
1271
- ) where C : Collection , C. Element == UTF16 . CodeUnit {
1275
+ with newElements: C ,
1276
+ of codeUnit: CodeUnit . Type
1277
+ ) where C : Collection , C. Element == UTF16 . CodeUnit ,
1278
+ CodeUnit : FixedWidthInteger & UnsignedInteger {
1272
1279
_precondition ( bounds. lowerBound >= 0 ,
1273
1280
" replaceSubrange: subrange start precedes String start " )
1274
1281
1275
1282
let newCount : Int = numericCast ( newElements. count)
1276
1283
let deltaCount = newCount - bounds. count
1277
1284
let paramsOpt = allocationParametersForMutableStorage (
1278
- of: UTF16 . CodeUnit. self,
1285
+ of: CodeUnit . self,
1279
1286
unusedCapacity: Swift . max ( 0 , deltaCount) )
1280
1287
1281
1288
if _fastPath ( paramsOpt == nil ) {
1282
1289
// We have unique native storage of the correct code unit,
1283
1290
// with enough capacity to do the replacement inline.
1284
- unowned(unsafe) let storage = _nativeStorage ( of: UTF16 . CodeUnit. self)
1291
+ unowned(unsafe) let storage = _nativeStorage ( of: CodeUnit . self)
1285
1292
_sanityCheck ( storage. unusedCapacity >= deltaCount)
1286
1293
let tailCount = storage. count - bounds. upperBound
1287
1294
_precondition ( tailCount >= 0 ,
@@ -1294,10 +1301,11 @@ extension _StringGuts {
1294
1301
count: tailCount)
1295
1302
}
1296
1303
// Copy new elements in place
1297
- let ( _, end) = UnsafeMutableBufferPointer (
1298
- start: dst,
1299
- count: newCount) . initialize ( from: newElements)
1300
- _precondition ( end == newCount, " Collection misreported its count " )
1304
+ var it = newElements. makeIterator ( )
1305
+ for p in dst ..< ( dst + newCount) {
1306
+ p. pointee = CodeUnit ( it. next ( ) !)
1307
+ }
1308
+ _precondition ( it. next ( ) == nil , " Collection misreported its count " )
1301
1309
storage. count += deltaCount
1302
1310
_nativeCount += deltaCount
1303
1311
_invariantCheck ( )
@@ -1309,7 +1317,7 @@ extension _StringGuts {
1309
1317
let params = paramsOpt. _unsafelyUnwrappedUnchecked
1310
1318
_precondition ( bounds. upperBound <= params. count,
1311
1319
" replaceSubrange: subrange extends past String end " )
1312
- let storage = _SwiftStringStorage< UTF16 . CodeUnit> . create(
1320
+ let storage = _SwiftStringStorage< CodeUnit> . create(
1313
1321
capacity: params. capacity,
1314
1322
count: params. count + deltaCount)
1315
1323
var dst = storage. start
@@ -1321,9 +1329,11 @@ extension _StringGuts {
1321
1329
dst += prefixRange. count
1322
1330
1323
1331
// Copy new data
1324
- let ( _, end) = UnsafeMutableBufferPointer (
1325
- start: dst, count: newCount) . initialize ( from: newElements)
1326
- _precondition ( end == newCount, " Collection misreported its count " )
1332
+ var it = newElements. makeIterator ( )
1333
+ for p in dst ..< ( dst + newCount) {
1334
+ p. pointee = CodeUnit ( it. next ( ) !)
1335
+ }
1336
+ _precondition ( it. next ( ) == nil , " Collection misreported its count " )
1327
1337
dst += newCount
1328
1338
1329
1339
// Copy suffix from end of replaced range
@@ -1335,12 +1345,58 @@ extension _StringGuts {
1335
1345
self = _StringGuts ( storage)
1336
1346
_invariantCheck ( )
1337
1347
}
1348
+
1349
+ public mutating func replaceSubrange< C> (
1350
+ _ bounds: Range < Int > ,
1351
+ with newElements: C
1352
+ ) where C : Collection , C. Element == UTF16 . CodeUnit {
1353
+ if isASCII && !newElements. contains ( where: { $0 > 0x7f } ) {
1354
+ self . _replaceSubrange ( bounds, with: newElements, of: UInt8 . self)
1355
+ } else {
1356
+ self . _replaceSubrange ( bounds, with: newElements, of: UTF16 . CodeUnit. self)
1357
+ }
1358
+ }
1338
1359
}
1339
1360
1340
1361
//
1341
1362
// String API
1342
1363
//
1343
1364
1365
+ // UnicodeScalarView operations
1366
+ extension _StringGuts {
1367
+ @_inlineable // FIXME(sil-serialize-all)
1368
+ @_versioned // FIXME(sil-serialize-all)
1369
+ func _unicodeScalarWidth( startingAt offset: Int ) -> Int {
1370
+ if _slowPath ( _isOpaque) {
1371
+ return _asOpaque ( ) . _unicodeScalarWidth ( startingAt: offset)
1372
+ }
1373
+ if isASCII { return 1 }
1374
+ return _unmanagedUTF16View. _unicodeScalarWidth ( startingAt: offset)
1375
+ }
1376
+
1377
+ @_inlineable // FIXME(sil-serialize-all)
1378
+ @_versioned // FIXME(sil-serialize-all)
1379
+ func _unicodeScalarWidth( endingAt offset: Int ) -> Int {
1380
+ if _slowPath ( _isOpaque) {
1381
+ return _asOpaque ( ) . _unicodeScalarWidth ( endingAt: offset)
1382
+ }
1383
+ if isASCII { return 1 }
1384
+ return _unmanagedUTF16View. _unicodeScalarWidth ( endingAt: offset)
1385
+ }
1386
+
1387
+ @_inlineable // FIXME(sil-serialize-all)
1388
+ @_versioned // FIXME(sil-serialize-all)
1389
+ func _decodeUnicodeScalar( startingAt offset: Int ) -> UnicodeDecodingResult {
1390
+ if _slowPath ( _isOpaque) {
1391
+ return _asOpaque ( ) . _decodeUnicodeScalar ( startingAt: offset)
1392
+ }
1393
+ if isASCII {
1394
+ return _unmanagedASCIIView. _decodeUnicodeScalar ( startingAt: offset)
1395
+ }
1396
+ return _unmanagedUTF16View. _decodeUnicodeScalar ( startingAt: offset)
1397
+ }
1398
+ }
1399
+
1344
1400
// Some CharacterView operations
1345
1401
extension String {
1346
1402
/// Accesses the character at the given position.
0 commit comments