1111//===----------------------------------------------------------------------===//
1212
1313extension String . Index {
14+ private init ? < S: StringProtocol > (
15+ _ idx: String . Index , _genericWithin target: S
16+ ) {
17+ guard target. _wholeGuts. isOnGraphemeClusterBoundary ( idx) ,
18+ idx >= target. startIndex && idx <= target. endIndex
19+ else {
20+ return nil
21+ }
22+
23+ self = idx
24+ }
25+
26+ /// Creates an index in the given string that corresponds exactly to the
27+ /// specified position.
28+ ///
29+ /// If the index passed as `sourcePosition` represents the start of an
30+ /// extended grapheme cluster---the element type of a string---then the
31+ /// initializer succeeds.
32+ ///
33+ /// The following example converts the position of the Unicode scalar `"e"`
34+ /// into its corresponding position in the string. The character at that
35+ /// position is the composed `"é"` character.
36+ ///
37+ /// let cafe = "Cafe\u{0301}"
38+ /// print(cafe)
39+ /// // Prints "Café"
40+ ///
41+ /// let scalarsIndex = cafe.unicodeScalars.firstIndex(of: "e")!
42+ /// let stringIndex = String.Index(scalarsIndex, within: cafe)!
43+ ///
44+ /// print(cafe[...stringIndex])
45+ /// // Prints "Café"
46+ ///
47+ /// If the index passed as `sourcePosition` doesn't have an exact
48+ /// corresponding position in `target`, the result of the initializer is
49+ /// `nil`. For example, an attempt to convert the position of the combining
50+ /// acute accent (`"\u{0301}"`) fails. Combining Unicode scalars do not have
51+ /// their own position in a string.
52+ ///
53+ /// let nextScalarsIndex = cafe.unicodeScalars.index(after: scalarsIndex)
54+ /// let nextStringIndex = String.Index(nextScalarsIndex, within: cafe)
55+ ///
56+ /// print(nextStringIndex)
57+ /// // Prints "nil"
58+ ///
59+ /// - Parameters:
60+ /// - sourcePosition: A position in a view of the `target` parameter.
61+ /// `sourcePosition` must be a valid index of at least one of the views
62+ /// of `target`.
63+ /// - target: The string referenced by the resulting index.
64+ public init ? ( _ sourcePosition: String . Index , within target: String ) {
65+ self . init ( sourcePosition, _genericWithin: target)
66+ }
67+
1468 /// Creates an index in the given string that corresponds exactly to the
1569 /// specified position.
1670 ///
@@ -49,14 +103,11 @@ extension String.Index {
49103 /// `sourcePosition` must be a valid index of at least one of the views
50104 /// of `target`.
51105 /// - target: The string referenced by the resulting index.
52- public init ? (
53- _ sourcePosition : String . Index ,
54- within target: String
106+ @ available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * )
107+ public init ? < S : StringProtocol > (
108+ _ sourcePosition : String . Index , within target: S
55109 ) {
56- guard target. _guts. isOnGraphemeClusterBoundary ( sourcePosition) else {
57- return nil
58- }
59- self = sourcePosition
110+ self . init ( sourcePosition, _genericWithin: target)
60111 }
61112
62113 /// Returns the position in the given UTF-8 view that corresponds exactly to
@@ -81,7 +132,7 @@ extension String.Index {
81132 /// position of a UTF-16 trailing surrogate returns `nil`.
82133 public func samePosition(
83134 in utf8: String . UTF8View
84- ) -> String . UTF8View . Index ? {
135+ ) -> String . UTF8View . Index ? {
85136 return String . UTF8View. Index ( self , within: utf8)
86137 }
87138
0 commit comments