@@ -105,18 +105,59 @@ extension NSRange {
105
105
//===----------------------------------------------------------------------===//
106
106
107
107
extension NSRange {
108
- public init ( _ x: Range < Int > ) {
109
- location = x. lowerBound
110
- length = x. count
111
- }
108
+ public init < R: RangeExpression > ( _ rangeExpression: R )
109
+ where R. Bound: FixedWidthInteger , R. Bound. Stride : SignedInteger {
110
+ let range = rangeExpression. relative ( to: 0 ..< R . Bound. max)
111
+ let start : Int = numericCast ( range. lowerBound)
112
+ let end : Int = numericCast ( range. upperBound)
113
+ self = NSRange ( location: start, length: end - start)
114
+ }
115
+
116
+ public init < R: RangeExpression , S: StringProtocol > ( _ rangeExpression: R , in string: S )
117
+ where R. Bound == String . Index , S. Index == String . Index {
118
+ let range = rangeExpression. relative ( to: string)
119
+ let start = range. lowerBound. samePosition ( in: string. utf16)
120
+ let end = range. upperBound. samePosition ( in: string. utf16)
121
+ let location = string. utf16. distance ( from: string. utf16. startIndex, to: start)
122
+ let length = string. utf16. distance ( from: start, to: end)
123
+ self = NSRange ( location: location, length: length)
124
+ }
112
125
113
- // FIXME(ABI)#75 (Conditional Conformance): this API should be an extension on Range.
114
- // Can't express it now because the compiler does not support conditional
115
- // extensions with type equality constraints.
116
- public func toRange( ) -> Range < Int > ? {
117
- if location == NSNotFound { return nil }
118
- return location..< ( location+ length)
119
- }
126
+ @available ( swift, deprecated: 4 , renamed: " Range.init(_:) " )
127
+ public func toRange( ) -> Range < Int > ? {
128
+ if location == NSNotFound { return nil }
129
+ return location..< ( location+ length)
130
+ }
131
+ }
132
+
133
+ extension Range where Bound: BinaryInteger {
134
+ public init ? ( _ range: NSRange ) {
135
+ guard range. location != NSNotFound else { return nil }
136
+ self . init ( uncheckedBounds: ( numericCast ( range. lowerBound) , numericCast ( range. upperBound) ) )
137
+ }
138
+ }
139
+
140
+ // This additional overload will mean Range.init(_:) defaults to Range<Int> when
141
+ // no additional type context is provided:
142
+ extension Range where Bound == Int {
143
+ public init ? ( _ range: NSRange ) {
144
+ guard range. location != NSNotFound else { return nil }
145
+ self . init ( uncheckedBounds: ( range. lowerBound, range. upperBound) )
146
+ }
147
+ }
148
+
149
+ extension Range where Bound == String . Index {
150
+ public init ? ( _ range: NSRange , in string: String ) {
151
+ let u = string. utf16
152
+ guard range. location != NSNotFound,
153
+ let start = u. index ( u. startIndex, offsetBy: range. location, limitedBy: u. endIndex) ,
154
+ let end = u. index ( u. startIndex, offsetBy: range. location + range. length, limitedBy: u. endIndex) ,
155
+ let lowerBound = String . Index ( start, within: string) ,
156
+ let upperBound = String . Index ( end, within: string)
157
+ else { return nil }
158
+
159
+ self = lowerBound..< upperBound
160
+ }
120
161
}
121
162
122
163
extension NSRange : CustomReflectable {
@@ -130,3 +171,4 @@ extension NSRange : CustomPlaygroundQuickLookable {
130
171
return . range( Int64 ( location) , Int64 ( length) )
131
172
}
132
173
}
174
+
0 commit comments