@@ -1415,6 +1415,66 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1415
1415
}
1416
1416
}
1417
1417
1418
+ @inlinable
1419
+ @usableFromInline
1420
+ @_alwaysEmitIntoClient
1421
+ internal mutating func _truncateOrZeroExtend( toCount newCount: Int ) {
1422
+ switch self {
1423
+ case . empty:
1424
+ if newCount == 0 {
1425
+ return
1426
+ } else if InlineData . canStore ( count: newCount) {
1427
+ self = . inline( InlineData ( count: newCount) )
1428
+ } else if InlineSlice . canStore ( count: newCount) {
1429
+ self = . slice( InlineSlice ( count: newCount) )
1430
+ } else {
1431
+ self = . large( LargeSlice ( count: newCount) )
1432
+ }
1433
+ case . inline( var inline) :
1434
+ if newCount == 0 {
1435
+ self = . empty
1436
+ } else if InlineData . canStore ( count: newCount) {
1437
+ guard inline. count != newCount else { return }
1438
+ inline. count = newCount
1439
+ self = . inline( inline)
1440
+ } else if InlineSlice . canStore ( count: newCount) {
1441
+ var slice = InlineSlice ( inline)
1442
+ slice. count = newCount
1443
+ self = . slice( slice)
1444
+ } else {
1445
+ var slice = LargeSlice ( inline)
1446
+ slice. count = newCount
1447
+ self = . large( slice)
1448
+ }
1449
+ case . slice( var slice) :
1450
+ if newCount == 0 && slice. startIndex == 0 {
1451
+ self = . empty
1452
+ } else if slice. startIndex == 0 && InlineData . canStore ( count: newCount) {
1453
+ self = . inline( InlineData ( slice, count: newCount) )
1454
+ } else if InlineSlice . canStore ( count: newCount + slice. startIndex) {
1455
+ guard slice. count != newCount else { return }
1456
+ self = . empty // TODO: remove this when mgottesman lands optimizations
1457
+ slice. count = newCount
1458
+ self = . slice( slice)
1459
+ } else {
1460
+ var newSlice = LargeSlice ( slice)
1461
+ newSlice. count = newCount
1462
+ self = . large( newSlice)
1463
+ }
1464
+ case . large( var slice) :
1465
+ if newCount == 0 && slice. startIndex == 0 {
1466
+ self = . empty
1467
+ } else if slice. startIndex == 0 && InlineData . canStore ( count: newCount) {
1468
+ self = . inline( InlineData ( slice, count: newCount) )
1469
+ } else {
1470
+ guard slice. count != newCount else { return }
1471
+ self = . empty // TODO: remove this when mgottesman lands optimizations
1472
+ slice. count = newCount
1473
+ self = . large( slice)
1474
+ }
1475
+ }
1476
+ }
1477
+
1418
1478
@inlinable // This is @inlinable as reasonably small.
1419
1479
var count : Int {
1420
1480
get {
@@ -1426,69 +1486,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1426
1486
}
1427
1487
}
1428
1488
set ( newValue) {
1429
- // HACK: The definition of this inline function takes an inout reference to self, giving the optimizer a unique referencing guarantee.
1430
- // This allows us to avoid excessive retain-release traffic around modifying enum values, and inlining the function then avoids the additional frame.
1431
- @inline ( __always)
1432
- func apply( _ representation: inout _Representation , _ newValue: Int ) -> _Representation ? {
1433
- switch representation {
1434
- case . empty:
1435
- if newValue == 0 {
1436
- return nil
1437
- } else if InlineData . canStore ( count: newValue) {
1438
- return . inline( InlineData ( count: newValue) )
1439
- } else if InlineSlice . canStore ( count: newValue) {
1440
- return . slice( InlineSlice ( count: newValue) )
1441
- } else {
1442
- return . large( LargeSlice ( count: newValue) )
1443
- }
1444
- case . inline( var inline) :
1445
- if newValue == 0 {
1446
- return . empty
1447
- } else if InlineData . canStore ( count: newValue) {
1448
- guard inline. count != newValue else { return nil }
1449
- inline. count = newValue
1450
- return . inline( inline)
1451
- } else if InlineSlice . canStore ( count: newValue) {
1452
- var slice = InlineSlice ( inline)
1453
- slice. count = newValue
1454
- return . slice( slice)
1455
- } else {
1456
- var slice = LargeSlice ( inline)
1457
- slice. count = newValue
1458
- return . large( slice)
1459
- }
1460
- case . slice( var slice) :
1461
- if newValue == 0 && slice. startIndex == 0 {
1462
- return . empty
1463
- } else if slice. startIndex == 0 && InlineData . canStore ( count: newValue) {
1464
- return . inline( InlineData ( slice, count: newValue) )
1465
- } else if InlineSlice . canStore ( count: newValue + slice. startIndex) {
1466
- guard slice. count != newValue else { return nil }
1467
- representation = . empty // TODO: remove this when mgottesman lands optimizations
1468
- slice. count = newValue
1469
- return . slice( slice)
1470
- } else {
1471
- var newSlice = LargeSlice ( slice)
1472
- newSlice. count = newValue
1473
- return . large( newSlice)
1474
- }
1475
- case . large( var slice) :
1476
- if newValue == 0 && slice. startIndex == 0 {
1477
- return . empty
1478
- } else if slice. startIndex == 0 && InlineData . canStore ( count: newValue) {
1479
- return . inline( InlineData ( slice, count: newValue) )
1480
- } else {
1481
- guard slice. count != newValue else { return nil }
1482
- representation = . empty // TODO: remove this when mgottesman lands optimizations
1483
- slice. count = newValue
1484
- return . large( slice)
1485
- }
1486
- }
1487
- }
1488
-
1489
- if let rep = apply ( & self , newValue) {
1490
- self = rep
1491
- }
1489
+ _truncateOrZeroExtend ( toCount: newValue)
1492
1490
}
1493
1491
}
1494
1492
@@ -2388,16 +2386,16 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
2388
2386
// Copy as much as we can in one shot.
2389
2387
let underestimatedCount = elements. underestimatedCount
2390
2388
let originalCount = _representation. count
2391
- _representation. count += underestimatedCount
2392
- var ( iter, endIndex ) : ( S . Iterator , Int ) = _representation. withUnsafeMutableBytes { buffer in
2389
+ _representation. _truncateOrZeroExtend ( toCount : originalCount + underestimatedCount)
2390
+ var ( iter, copiedCount ) : ( S . Iterator , Int ) = _representation. withUnsafeMutableBytes { buffer in
2393
2391
let start = buffer. baseAddress!. assumingMemoryBound ( to: UInt8 . self) + originalCount
2394
2392
let b = UnsafeMutableBufferPointer ( start: start, count: buffer. count - originalCount)
2395
2393
return elements. _copyContents ( initializing: b)
2396
2394
}
2397
- guard endIndex == underestimatedCount else {
2395
+ guard copiedCount == underestimatedCount else {
2398
2396
// We can't trap here. We have to allow an underfilled buffer
2399
2397
// to emulate the previous implementation.
2400
- _representation. replaceSubrange ( originalCount + endIndex ..< _representation . endIndex , with : nil , count : 0 )
2398
+ _representation. _truncateOrZeroExtend ( toCount : originalCount + copiedCount )
2401
2399
return
2402
2400
}
2403
2401
0 commit comments