File tree Expand file tree Collapse file tree 3 files changed +44
-2
lines changed Expand file tree Collapse file tree 3 files changed +44
-2
lines changed Original file line number Diff line number Diff line change @@ -81,6 +81,10 @@ extension Character {
81
81
internal func _invariantCheck( ) {
82
82
_internalInvariant ( _str. count == 1 )
83
83
_internalInvariant ( _str. _guts. isFastUTF8)
84
+
85
+ // TODO(@eject): Switch to a helper property on StringObject/StringGuts.
86
+ _internalInvariant (
87
+ _str. _guts. isSmall || _str. _guts. _object. _countAndFlags. isTailAllocated)
84
88
}
85
89
#endif // INTERNAL_CHECKS_ENABLED
86
90
}
@@ -173,7 +177,17 @@ extension Character :
173
177
" Can't form a Character from an empty String " )
174
178
_debugPrecondition ( s. index ( after: s. startIndex) == s. endIndex,
175
179
" Can't form a Character from a String containing more than one extended grapheme cluster " )
176
- self . init ( unchecked: s)
180
+
181
+ // TODO(@eject): Switch to a helper property on StringObject/StringGuts.
182
+ if _fastPath (
183
+ s. _guts. isSmall || s. _guts. _object. _countAndFlags. isTailAllocated
184
+ ) {
185
+ self . init ( unchecked: s)
186
+ return
187
+ }
188
+
189
+ // TODO(@eject): Outline this
190
+ self . init ( unchecked: s. _withUTF8 { String . _uncheckedFromUTF8 ( $0) } )
177
191
}
178
192
}
179
193
Original file line number Diff line number Diff line change @@ -617,9 +617,10 @@ extension _StringObject {
617
617
isNativelyStored: set for native stored strings
618
618
- `largeAddressBits` holds an instance of `_StringStorage`.
619
619
- I.e. the start of the code units is at the stored address + `nativeBias`
620
- isTailAllocated: start of the code units is at the stored address + `nativeBias`
620
+ isTailAllocated: contiguous UTF-8 code units starts at address + `nativeBias`
621
621
- `isNativelyStored` always implies `isTailAllocated`, but not vice versa
622
622
(e.g. literals)
623
+ - `isTailAllocated` always implies `isFastUTF8`
623
624
TBD: Reserved for future usage
624
625
- Setting a TBD bit to 1 must be semantically equivalent to 0
625
626
- I.e. it can only be used to "cache" fast-path information in the future
@@ -1073,6 +1074,9 @@ extension _StringObject {
1073
1074
} else {
1074
1075
_internalInvariant ( isLarge)
1075
1076
_internalInvariant ( largeCount == count)
1077
+ if _countAndFlags. isTailAllocated {
1078
+ _internalInvariant ( providesFastUTF8)
1079
+ }
1076
1080
if providesFastUTF8 && largeFastIsTailAllocated {
1077
1081
_internalInvariant ( !isSmall)
1078
1082
_internalInvariant ( !largeIsCocoa)
Original file line number Diff line number Diff line change @@ -75,5 +75,29 @@ StringBridgeTests.test("Tagged NSString") {
75
75
#endif // not 32bit
76
76
}
77
77
78
+ func returnOne< T> ( _ t: T ) -> Int { return 1 }
79
+ StringBridgeTests . test ( " Character from NSString " ) {
80
+ // NOTE: Using hard-coded literals to directly construct NSStrings
81
+ let ns1 = " A " as NSString
82
+ let ns2 = " A \u{301} " as NSString
83
+ let ns3 = " 𓁹͇͈͉͍͎͊͋͌ͧͨͩͪͫͬͭͮ͏̛͓͔͕͖͙͚̗̘̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂̓̈́͆ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ͅ " as NSString
84
+
85
+ let c1 = Character ( ns1 as String )
86
+ let c2 = Character ( ns2 as String )
87
+ let c3 = Character ( ns3 as String )
88
+
89
+ expectEqual ( " A " , String ( c1) )
90
+ expectNotNil ( String ( c1) . utf8. withContiguousStorageIfAvailable ( returnOne) )
91
+
92
+ expectEqual ( " A \u{301} " , String ( c2) )
93
+ expectNotNil ( String ( c2) . utf8. withContiguousStorageIfAvailable ( returnOne) )
94
+ expectNil ( ( ns2 as String ) . utf8. withContiguousStorageIfAvailable ( returnOne) )
95
+
96
+ expectEqual ( " 𓁹͇͈͉͍͎͊͋͌ͧͨͩͪͫͬͭͮ͏̛͓͔͕͖͙͚̗̘̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂̓̈́͆ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ͅ " , String ( c3) )
97
+ expectNotNil ( String ( c3) . utf8. withContiguousStorageIfAvailable ( returnOne) )
98
+ expectNil ( ( ns3 as String ) . utf8. withContiguousStorageIfAvailable ( returnOne) )
99
+ }
100
+
101
+
78
102
runAllTests ( )
79
103
You can’t perform that action at this time.
0 commit comments