@@ -97,12 +97,19 @@ public struct Substring: Sendable {
97
97
@usableFromInline
98
98
internal var _slice : Slice < String >
99
99
100
+ @_alwaysEmitIntoClient // Swift 5.7
100
101
@inline ( __always)
101
102
internal init ( _unchecked slice: Slice < String > ) {
102
103
self . _slice = slice
103
104
_invariantCheck ( )
104
105
}
105
106
107
+ @_alwaysEmitIntoClient // Swift 5.7
108
+ @inline ( __always)
109
+ internal init ( _unchecked guts: _StringGuts , bounds: Range < Index > ) {
110
+ self . init ( _unchecked: Slice ( base: String ( guts) , bounds: bounds) )
111
+ }
112
+
106
113
@usableFromInline // This used to be @inlinable before 5.7
107
114
@available ( * , deprecated) // Use `init(_unchecked:)` in new code.
108
115
internal init ( _ slice: Slice < String > ) {
@@ -728,9 +735,7 @@ extension Substring {
728
735
/// Creates an instance that slices `base` at `_bounds`.
729
736
@inlinable
730
737
internal init ( _ base: String . UTF8View , _bounds: Range < Index > ) {
731
- _slice = Slice (
732
- base: String ( base. _guts) . utf8,
733
- bounds: _bounds)
738
+ _slice = Slice ( base: base, bounds: _bounds)
734
739
}
735
740
736
741
@_alwaysEmitIntoClient @inline ( __always)
@@ -848,7 +853,8 @@ extension Substring {
848
853
@inlinable
849
854
public var utf8 : UTF8View {
850
855
get {
851
- return base. utf8 [ startIndex..< endIndex]
856
+ // No need for index validation
857
+ UTF8View ( base. utf8, _bounds: _bounds)
852
858
}
853
859
set {
854
860
self = Substring ( newValue)
@@ -859,9 +865,12 @@ extension Substring {
859
865
///
860
866
/// - Complexity: O(1)
861
867
public init ( _ content: UTF8View ) {
862
- self = String (
863
- content. _slice. _base. _guts
864
- ) [ content. startIndex..< content. endIndex]
868
+ // Note: We can trust that `content`'s bounds are valid, but they may not be
869
+ // scalar aligned.
870
+ let lower = content. _wholeGuts. scalarAlign ( content. startIndex)
871
+ let upper = content. _wholeGuts. scalarAlign ( content. endIndex)
872
+ let bounds = Range ( _uncheckedBounds: ( lower, upper) )
873
+ self . init ( _unchecked: content. _wholeGuts, bounds: bounds)
865
874
}
866
875
}
867
876
@@ -873,9 +882,9 @@ extension String {
873
882
/// - Complexity: O(N), where N is the length of the resulting `String`'s
874
883
/// UTF-16.
875
884
public init ? ( _ codeUnits: Substring . UTF8View ) {
876
- let guts = codeUnits. _slice . _base . _guts
877
- guard guts. isOnUnicodeScalarBoundary ( codeUnits. _slice . startIndex) ,
878
- guts. isOnUnicodeScalarBoundary ( codeUnits. _slice . endIndex) else {
885
+ let guts = codeUnits. _wholeGuts
886
+ guard guts. isOnUnicodeScalarBoundary ( codeUnits. startIndex) ,
887
+ guts. isOnUnicodeScalarBoundary ( codeUnits. endIndex) else {
879
888
return nil
880
889
}
881
890
@@ -1001,7 +1010,8 @@ extension Substring {
1001
1010
@inlinable
1002
1011
public var utf16 : UTF16View {
1003
1012
get {
1004
- return base. utf16 [ startIndex..< endIndex]
1013
+ // No need for index validation
1014
+ UTF16View ( base. utf16, _bounds: _bounds)
1005
1015
}
1006
1016
set {
1007
1017
self = Substring ( newValue)
@@ -1012,9 +1022,12 @@ extension Substring {
1012
1022
///
1013
1023
/// - Complexity: O(1)
1014
1024
public init ( _ content: UTF16View ) {
1015
- self = String (
1016
- content. _slice. _base. _guts
1017
- ) [ content. startIndex..< content. endIndex]
1025
+ // Note: We can trust that `content`'s bounds are valid, but they may not be
1026
+ // scalar aligned.
1027
+ let lower = content. _wholeGuts. scalarAlign ( content. startIndex)
1028
+ let upper = content. _wholeGuts. scalarAlign ( content. endIndex)
1029
+ let bounds = Range ( _uncheckedBounds: ( lower, upper) )
1030
+ self . init ( _unchecked: content. _wholeGuts, bounds: bounds)
1018
1031
}
1019
1032
}
1020
1033
@@ -1026,9 +1039,9 @@ extension String {
1026
1039
/// - Complexity: O(N), where N is the length of the resulting `String`'s
1027
1040
/// UTF-16.
1028
1041
public init ? ( _ codeUnits: Substring . UTF16View ) {
1029
- let guts = codeUnits. _slice . _base . _guts
1030
- guard guts. isOnUnicodeScalarBoundary ( codeUnits. _slice . startIndex) ,
1031
- guts. isOnUnicodeScalarBoundary ( codeUnits. _slice . endIndex) else {
1042
+ let guts = codeUnits. _wholeGuts
1043
+ guard guts. isOnUnicodeScalarBoundary ( codeUnits. startIndex) ,
1044
+ guts. isOnUnicodeScalarBoundary ( codeUnits. endIndex) else {
1032
1045
return nil
1033
1046
}
1034
1047
@@ -1042,6 +1055,7 @@ extension Substring {
1042
1055
internal var _slice : Slice < String . UnicodeScalarView >
1043
1056
1044
1057
/// Creates an instance that slices `base` at `_bounds`.
1058
+ @_alwaysEmitIntoClient
1045
1059
internal init (
1046
1060
_unchecked base: String . UnicodeScalarView , bounds: Range < Index >
1047
1061
) {
@@ -1164,7 +1178,8 @@ extension Substring {
1164
1178
@inlinable
1165
1179
public var unicodeScalars : UnicodeScalarView {
1166
1180
get {
1167
- return base. unicodeScalars [ startIndex..< endIndex]
1181
+ // No need to validate any indices.
1182
+ UnicodeScalarView ( _unchecked: base. unicodeScalars, bounds: _bounds)
1168
1183
}
1169
1184
set {
1170
1185
self = Substring ( newValue)
@@ -1175,9 +1190,9 @@ extension Substring {
1175
1190
///
1176
1191
/// - Complexity: O(1)
1177
1192
public init ( _ content: UnicodeScalarView ) {
1178
- self = String (
1179
- content. _slice . _base . _guts
1180
- ) [ content . startIndex ..< content . endIndex ]
1193
+ // No need to validate any indices.
1194
+ let slice = Slice ( base : String ( content. _wholeGuts ) , bounds : content . _bounds )
1195
+ self . init ( _unchecked : slice )
1181
1196
}
1182
1197
}
1183
1198
0 commit comments